JS 刷 Leetcode:167.两数之和 II - 输入有序数组

简介: JS 刷 Leetcode:167.两数之和 II - 输入有序数组

1. 题目

给定一个已按照 非递减顺序排列  的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。

示例 1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

示例 2:

输入:numbers = [2,3,4], target = 6
输出:[1,3]

示例 3:

输入:numbers = [-1,0], target = -1
输出:[1,2]

 

提示:

  • 2 <= numbers.length <= 3 * 104
  • -1000 <= numbers[i] <= 1000
  • numbers 按 非递减顺序 排列
  • -1000 <= target <= 1000
  • 仅存在一个有效答案
  • 通过次数345,963提交次数58

2. 前言

这道题可以使用1. 两数之和的解法,使用 O(n2)的时间复杂度和O(1) 的空间复杂度暴力求解,或者借助哈希表使用O(n) 的时间复杂度和 O(n) 的空间复杂度求解。但是这两种解法都是针对无序数组的,没有利用到输入数组有序的性质。利用输入数组有序的性质,可以得到时间复杂度和空间复杂度更优的解法。

3.二分查找

先固定一个数,另一位数通过二分法来查找

/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
 var twoSum = function(numbers, target) {
  const len = numbers.length
  for(let i = 0; i < len - 1; i++) {
    let left = i + 1
    let right = len - 1
    const needNum = target - numbers[i]
    while(left <= right) {
      const mid = (left + right) >> 1
      if(numbers[mid] === needNum) {
        return [i + 1, mid + 1]
      }else if(numbers[mid] < needNum) {
        left = mid + 1
      } else if(numbers[mid] > needNum) {
        right = mid - 1
      }
    }
  }
};

复杂度分析:

  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(1)

image.png

4. 双指针

初始时两个指针分别指向第一个元素位置和最后一个元素的位置。每次计算两个指针指向的两个元素之和,并和目标值比较。如果两个元素之和等于目标值,则发现了唯一解。如果两个元素之和小于目标值,则将左侧指针右移一位。如果两个元素之和大于目标值,则将右侧指针左移一位。移动指针之后,重复上述操作,直到找到答案。

/**
 * @param {number[]} numbers
 * @param {number} target
 * @return {number[]}
 */
 var twoSum = function(numbers, target) {
  let left = 0,right = numbers.length - 1
  while(left < right) {
    const sum = numbers[left] + numbers[right]
    if(sum > target) {
      right--
    } else if(sum < target) {
      left++
    } else {
      return [left + 1, right + 1]
    }
  }
};

复杂度分析

  • 时间复杂度:O(n),其中 nn 是数组的长度。两个指针移动的总次数最多为 n 次。
  • 空间复杂度:O(1)。

image.png

相关文章
|
4月前
leetCode(删除有序数组中的重复项)
如何在不使用额外空间的情况下,通过双指针法原地删除有序数组中的重复项。
47 2
|
6月前
|
存储 Java API
LeetCode------合并两个有序数组(4)【数组】
这篇文章介绍了LeetCode上的"合并两个有序数组"问题,并提供了三种解法:第一种是使用Java的Arrays.sort()方法直接对合并后的数组进行排序;第二种是使用辅助数组和双指针技术进行合并;第三种则是从后向前的双指针方法,避免了使用额外的辅助数组。
LeetCode------合并两个有序数组(4)【数组】
|
4月前
|
C++
Leetcode第一题(两数之和)
这篇文章介绍了解决LeetCode第一题“两数之和”的两种方法:暴力法和哈希表法,并提供了相应的C++代码实现。
65 0
Leetcode第一题(两数之和)
|
6月前
|
算法
LeetCode第26题删除有序数组中的重复项
这篇文章介绍了LeetCode第26题"删除有序数组中的重复项"的解题方法,通过使用双指针技巧,高效地去除数组中的相邻重复元素。
LeetCode第26题删除有序数组中的重复项
|
4月前
【LeetCode 48】108.将有序数组转换为二叉搜索树
【LeetCode 48】108.将有序数组转换为二叉搜索树
59 0
|
4月前
|
存储 C++ 容器
【LeetCode 13】1.两数之和
【LeetCode 13】1.两数之和
28 0
|
6月前
|
算法
LeetCode第80题删除有序数组中的重复项 II
文章介绍了LeetCode第80题"删除有序数组中的重复项 II"的解法,利用双指针技术在O(1)空间复杂度内原地删除重复元素,并总结了双指针技术在处理有序数组问题中的应用。
LeetCode第80题删除有序数组中的重复项 II
|
6月前
|
算法
LeetCode第88题合并两个有序数组
文章分享了LeetCode第88题"合并两个有序数组"的解法,通过从后向前的合并策略避免了数组元素的前移,使用三个指针高效地完成了合并过程。
|
6月前
|
存储 索引
LeetCode------两数之和(3)【数组】
这篇文章介绍了LeetCode上的"两数之和"问题,提供了两种解法:一种是暴力求解法,通过双层循环遍历数组元素对查找两数之和为目标值的索引,时间复杂度为O(n^2);另一种是使用HashMap优化,通过存储元素值和索引,时间复杂度降低到O(n)。
LeetCode------两数之和(3)【数组】
|
6月前
|
算法
LeetCode第1题两数之和
该文章介绍了 LeetCode 第 1 题两数之和的解法,通过使用 HashMap 来记录数组元素及其下标,以 O(n)的时间复杂度解决问题。

热门文章

最新文章