一、問題描述
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.
Note:
- 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.
Example:
Input: numbers = [2,7,11,15], target = 9 Output: [1,2] Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.
注意事項:返回的是索引,不是下標。
二、解題思路
其實,如果2 Sum和3 Sum的問題搞定了,這道題真的很easy。就是left和right的移動問題
三、代碼實現(類似於快速排序)
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
unordered_map<int,int> result;
vector<int> vec;
int left = 0;
int right = numbers.size()-1;
while(left < right){
int sum = numbers[left] + numbers[right];
if(sum > target){
right--;
} else if(sum < target){
left++;
} else {
//題目要求,索引下標加1了
vec.push_back(left+1);
vec.push_back(right+1);
left++;
right--;
}
}
return vec;
}
};
四、這道題的變種
1. 如果有多對數字的和等於target,輸出兩個數的乘積最小的。
#include <climits>
class Solution
{
public:
vector<int> FindNumbersWithSum(vector<int> a,int sum)
{
if(a.size()<2) return vector<int>();
int min_product = INT_MAX;
int left = 0,
right = a.size()-1;
int a1,a2;
bool find_flag = false;
while(left < right) //從兩邊開始往中間掃描
{
int cursum = a[left] + a[right];
if(cursum > sum) right--;
else if(cursum < sum) left++;
else
{
//因爲對於遞增序列,一定有x*y < (x+a)*(y-a),故這裏其實可以不用判斷
//從兩邊開始往中間掃描時,找到的第一個即爲乘機最小的一對數
if(a[left]*a[right] < min_product)
{
find_flag = true;
min_product = a[left]*a[right];
a1 = a[left];
a2 = a[right];
}
left++; //繼續掃描
}
}
if(find_flag) return vector<int>{a1,a2};
else return vector<int>();
}
};
2. 和爲sum的連續正數序列(至少包括兩個數,例如:100:[9,10,11,12,13,14,15,16]/[18,19,20,21,22]...)
class Solution
{
public:
vector<vector<int> > FindContinuousSequence(int sum)
{
vector<vector<int>> result;
if(sum < 3) return result; //至少需包含兩個數
int left = 1, right = 2; //序列從1開始
while(left < right) //注意從開頭開始掃描,直到left與right相遇
{
int cursum = (left+right)*(right - left + 1)/2; //用等差數列的求和公式
if(cursum < sum) right++;
else if(cursum > sum) left++;
else
{
vector<int> temp;
for(int i = left; i <= right; i++)
temp.push_back(i);
result.push_back(temp); //push符合要求的連續正數序列,不止一組
left++; //繼續下個序列的尋找
}
}
return result;
}
};