题目:
Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution and you may not use the same element twice.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
思路:
建议将这道题目和Two Sum I这道题目结合起来学习。
1、朴素版:最朴素的思路仍然是采用two pointers来实现:初始化两个指针为数组的两端,然后判断他们的和,如果和大于target,则左移右端指针;如果和小于target,则右移左端指针,直到找到和正好等于target或者左右指针相遇。可是这种思路的时间复杂度还是O(n)。
2、改进版:通过分析朴素版我发现,其实每次只将指针移动一位比较保守,没有充分利用数组有序的特点。所以在改进版中,当和大于target的时候,我直接在数组中搜索target - numbers[left]的位置,并且据此更新右端指针;当和小于target的时候,直接在数组中搜索target - numbers[right]的位置,并据此更新左端指针。这样就可以将时间复杂度进一步降低到O(logn)。
代码:
1、朴素版:
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
if (numbers.size() == 0) {
return {};
}
int left = 0, right = numbers.size() - 1;
while (left < right) {
int val = numbers[left] + numbers[right];
if (val == target) {
return vector<int>{left + 1, right + 1};
}
else if (val > target) {
--right;
}
else {
++left;
}
}
return {};
}
};
2、改进版:
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
if (numbers.size() == 0) {
return {};
}
int left = 0, right = numbers.size() - 1;
while (left < right) {
int val = numbers[left] + numbers[right];
if (val == target) {
return vector<int>{left + 1, right + 1};
}
else if (val > target) {
right = binarySearch(numbers, left + 1, right - 1, target - numbers[left]);
}
else {
left = binarySearch(numbers, left + 1, right - 1, target - numbers[right]);
}
}
return {};
}
private:
int binarySearch(vector<int>& numbers, int start, int end, int target) {
while (start < end) {
int mid = start + (end - start) / 2;
if (numbers[mid] == target) {
return mid;
}
else if (numbers[mid] > target) {
end = mid - 1;
}
else {
start = mid + 1;
}
}
return start;
}
};