167. 两数之和 II - 输入有序数组 Medium
给你一个下标从 1 开始的整数数组 numbers
,该数组已按 非递减顺序排列,请你从数组中找出满足相加之和等于目标数 target
的两个数。如果设这两个数分别是 numbers[index1]
和 numbers[index2]
,则 1 <= index1 < index2 <= numbers.length
。
以长度为 2 的整数数组 [index1, index2]
的形式返回这两个整数的下标 index1
和 index2
。
你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
你所设计的解决方案必须只使用常量级的额外空间。
示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
解释:2 与 4 之和等于目标数 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
解释:-1 与 0 之和等于目标数 -1 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
解题思路
输入:一个整数数组 numbers
,一个目标值 target
输出:找出两个值相加等于 target
,返回他们的下标
本题属于 相向双指针 问题。
我们可以用一对相向双指针去不断的找出和为 target
的组合
当和 大于 target
时移动右指针,反之移动左指针,直到找到答案位置,注意下标是从 1 开始所以要返回 [left + 1, right + 1]
代码实现
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
# 初始化左右指针
left, right = 0, len(numbers) - 1
# 当左指针小于右指针时继续查找
while left < right:
# 当前两个指针指向数字的和
s = numbers[left] + numbers[right]
if s > target:
# 如果和大于目标值,说明右边数字太大,右指针左移
right -= 1
elif s < target:
# 如果和小于目标值,说明左边数字太小,左指针右移
left += 1
else:
# 找到目标组合,返回下标(题目要求下标从1开始)
return [left + 1, right + 1]
/**
* @param {number[]} numbers
* @param {number} target
* @return {number[]}
*/
var twoSum = function(numbers, target) {
let left = 0;
let right = numbers.length - 1;
while (left < right) {
const s = numbers[left] + numbers[right];
if (s > target) {
right --;
} else if (s < target) {
left ++;
} else {
return [left + 1, right + 1];
}
}
};
复杂度分析
时间复杂度:O(n)
空间复杂度:O(1)