思路
方法一:二分查找
在数组中找到两个数,使得它们的和等于目标值,可以首先固定第一个数,然后寻找第二个数,第二个数等于目标值减去第一个数的差。利用数组的有序性质,可以通过二分查找的方法寻找第二个数。为了避免重复寻找,在寻找第二个数时,只在第一个数的右侧寻找。
1 class Solution { 2 public: 3 vector<int> twoSum(vector<int>& numbers, int target) { 4 for(int i = 0; i < numbers.size(); ++i) { 5 int x = target - numbers[i]; 6 //二分查找x 7 int left = i+1, right = numbers.size()-1; 8 while(left <= right) { 9 int mid = (left + right)/2; 10 if(numbers[mid] < x) { 11 left = mid + 1; 12 } else if(numbers[mid] > x) { 13 right = mid - 1; 14 } else { 15 return vector<int>({i+1, mid+1}); 16 } 17 } 18 } 19 20 return vector<int>(); 21 } 22 };
方法二:首尾双指针
初始时两个指针分别指向第一个元素位置和最后一个元素的位置。每次计算两个指针指向的两个元素之和,并和目标值比较。如果两个元素之和等于目标值,则发现了唯一解。如果两个元素之和小于目标值,则将左侧指针右移一位。如果两个元素之和大于目标值,则将右侧指针左移一位。移动指针之后,重复上述操作,直到找到答案。
1 class Solution { 2 public: 3 vector<int> twoSum(vector<int>& numbers, int target) { 4 int i = 0, j = numbers.size() - 1; 5 while(i < j) { //题目有解,i不可能越过j 6 if(numbers[i] + numbers[j] < target) { 7 ++i; 8 } else if(numbers[i] + numbers[j] > target) { 9 --j; 10 } else { 11 return vector<int>({i+1, j+1}); 12 } 13 } 14 15 return vector<int>(); 16 } 17 };