动机总是能战胜天赋。

题目描述:

两数之和 II - 输入有序数组

给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1]numbers[index2] ,则 1 <= index1 < index2 <= numbers.length

以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1index2

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

你所设计的解决方案必须只使用常量级的额外空间。

解题代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
int i = 0, j = numbers.size() - 1;
while(i < j){
if(numbers[i] + numbers[j] == target){
return {i + 1 , j + 1};
}
if(numbers[j] > target - numbers[i]){
j--;
}else{
i++;
}
}
return {};
}
};

image-20231028203000162

解读与收获:

缪莎!如果采用暴力方法,一个一个试,那时间复杂度是o(m * n),非常滴高。因为题目给的是有序数组,随灵光一现,双指针(i,j)一个从头遍历,一个从尾。过程中先固定i,然后进行判断,如果i和j就是题解,那直接返回(i+1,j+1),如果numbers[j] > target - numbers[i],那说明在j前面可能会出现想要的值,故j–前移(i固定),若在前移过程中发现numbers[j] < target - numbers[i],说明不存在当前i对应的值,故j不动i++进行后移,因为i对应的值变大了,target - numbers[i]值变小,遂可以继续比较,重复以上过程。

总结一下就是,固定i,然后根据i找对应的j,如果没找到,则i后移重新找,这样通过一遍遍历就能解决问题,妙!