LeetCode 167. 两数之和 II - 输入有序数组 思考分析
目錄
- 1、暴力,超時
- 2、雙指針+滑動窗口+條件限制 AC
- 3、觀看題解(吸取他人經驗)
- 1、二分查找
- 2、雙指針
- 3、雙指針+二分查找
給定一個已按照升序排列 的有序數組,找到兩個數使得它們相加之和等于目標數。
函數應該返回這兩個下標值 index1 和 index2,其中 index1 必須小于 index2。
說明:
返回的下標值(index1 和 index2)不是從零開始的。
你可以假設每個輸入只對應唯一的答案,而且你不可以重復使用相同的元素。
示例:
輸入: numbers = [2, 7, 11, 15], target = 9
輸出: [1,2]
解釋: 2 與 7 之和等于目標數 9 。因此 index1 = 1, index2 = 2 。
1、暴力,超時
class Solution { public:vector<int> twoSum(vector<int>& numbers, int target) {int n = numbers.size();int flag=0;vector<int> res;for(int i=0;i<n;i++){flag=0;for(int j=i+1;j<n;j++){if(numbers[i]+numbers[j]==target){res.emplace_back(i+1);res.emplace_back(j+1);flag=1;break;}}if(flag==1) break;}return res;} };2、雙指針+滑動窗口+條件限制 AC
在做題提交的過程中發現了幾處不容易想到的地方:
1、numbers中的元素是遞增的,但是這個遞增不是numbers[i]<numbers[i],而是numbers[i]<=numbers[i+1]
2、numbers中的元素有正有負,可能連續好幾個都是0
3、一開始我想:首先找到小于等于target的元素個數,這樣的話兩個值只需要在這些元素中找就可以了,但是事實并非如此。
例如:target=0,numbers[]= {-3,3,.....},如果用numbers[i]<=target,顯然只能到第一個元素,所以我又添加了一個限制條件:
(i>=1 && numbers[i-1]+numbers[i]==0)(因為觀察的是兩個元素相加的結果,所以這樣肯定是對的)
所以根據思考之后的修改為:
之后只需要在0~num_smaller_than_target-1的范圍內尋找兩個數就可以了!
然后使用雙指針,一開始L指向0,R指向num_smaller_than_target-1,并且保證L<R來循環
在循環過程中,時時注意sum = numbers[L]+numbers[R],
1、如果sum==target,說明我們已經找到值了,直接退出
2、如果sum<target,說明左值一定過小(右邊界由于是從大到小縮減的,此時不做改變,因為也不確定右邊界是大是小)
3、如果sum>target,說明右值一定過大,選擇減少右值(由于左邊界是從小到大的,此時不做改變,因為也不確定左邊界是大是小)
因為有要求:
所以我們來驗證一下重復結果是否輸出一致:
顯然正確。
3、觀看題解(吸取他人經驗)
1、二分查找
在數組中找到兩個數,使得它們的和等于目標值,可以首先固定第一個數,然后尋找第二個數,第二個數等于目標值減去第一個數的差。利用數組的有序性質,可以通過二分查找的方法尋找第二個數。為了避免重復尋找,在尋找第二個數時,只在第一個數的右側尋找。
class Solution { public:vector<int> twoSum(vector<int>& numbers, int target) {int n = numbers.size();int flag=0;for(int i=0;i<n;i++){int low = i+1;int high = n-1;while(low<=high){int mid = (high - low) / 2 + low;if (numbers[mid] == target - numbers[i]) {return {i + 1, mid + 1};}else if (numbers[mid] > target - numbers[i]) {high = mid - 1;} else {low = mid + 1;}}}return {};} };
總結:有序序列,查找值固定的數,可以考慮二分查找優化
2、雙指針
這是官方題解,和我一開始用的思路是一樣的,即雙指針。
而我做的一開始排除一些元素的方法好像沒有對時間有很多優化。。。
3、雙指針+二分查找
class Solution { public:vector<int> twoSum(vector<int>& numbers, int target) {int low = 0, high = numbers.size() - 1;while (low <high) {int middle = (low+high)*0.5;//1、目標在middle左側,重置highif(numbers[low]+numbers[middle]>target){high =middle-1;}//2、目標在middle右側,重置lowelse if(numbers[high]+numbers[middle]<target){low = middle+1;}//3、重置lowelse if(numbers[low]+numbers[high]<target){low++;}//4、重置highelse if(numbers[low]+numbers[high]>target){high--;}//5、sum等于targetelse{return {low+1,high+1}; }}return {0,0};} };
不知道為什么同樣的思路,用java速度可以達到1ms,而c++卻不行。
總結
以上是生活随笔為你收集整理的LeetCode 167. 两数之和 II - 输入有序数组 思考分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 当贝盒子h2如何连网线
- 下一篇: 原神寻星之旅第五关通关方法