给定一个已经 按升序排列 的数组,找到两个数使他们加起来的和等于特定数。
函数应该返回这两个数的下标,index1必须小于index2。注意返回的值不是 0-based。
你可以假设每个输入刚好只有一个答案
样例
给定数组为 [2,7,11,15]
,target = 9
返回 [1,2]
解题思路1:
暴力解法。遍历两遍,时间复杂度为O(n^2).
class Solution {
public:
/**
* @param nums: an array of Integer
* @param target: target = nums[index1] + nums[index2]
* @return: [index1 + 1, index2 + 1] (index1 < index2)
*/
vector<int> twoSum(vector<int> &nums, int target)
{
// write your code here
vector<int> res;
if(nums.size()<2)
return res;
for(int i=0;i<nums.size();i++)
{
for(int j=i+1;j<nums.size();j++)
{
int tmp = target - nums[i];
if(nums[j] == tmp)
{
res.push_back(i+1);
res.push_back(j+1);
return res;
}
}
}
}
};
解题思路2:
由于思路1没有用到有序这个条件,看到有序就想到二分搜索法,所以这里使用二分搜索来找target-nums[i]的值,时间复杂度为O(nlogn)如图:
class Solution {
public:
/**
* @param nums: an array of Integer
* @param target: target = nums[index1] + nums[index2]
* @return: [index1 + 1, index2 + 1] (index1 < index2)
*/
vector<int> twoSum(vector<int> &nums, int target)
{
// write your code here
vector<int> res;
for(int i=0;i<nums.size();i++)
{
int tmp = target - nums[i];//在剩余有序数组中查找这个数
//以下为二分搜索法
int l = i+1;
int r = nums.size()-1;
while(l<=r)
{
int mid = l + (r-l)/2;
if(nums[mid]==tmp)
{
res.push_back(i+1);
res.push_back(mid+1);
return res;
}
else if(nums[mid]<tmp)
l = mid + 1;
else
r = mid - 1;
}
}
}
};
解题思路3:
对撞指针法,时间复杂度只有O(n)。在有序数组两个数的和,一定是一个数在左边,一个数在右边,所以设立两个指针i,j分别指向数组的最左端与最右端,即最小值与最大值。
如果nums[i]+nums[j]==target,直接返回结果。
如果nums[i]+nums[j] < target,由于j已经是最大值,所以只能移动i,i++。
如果nums[i]+nums[j] > target,由于i已经是最小值,所以只能移动j,j--。
class Solution {
public:
/**
* @param nums: an array of Integer
* @param target: target = nums[index1] + nums[index2]
* @return: [index1 + 1, index2 + 1] (index1 < index2)
*/
vector<int> twoSum(vector<int> &nums, int target)
{
// write your code here
int i=0;
int j=nums.size()-1;
vector<int> res;
while(i<j)
{
if(nums[i]+nums[j]==target)
{
res.push_back(i+1);
res.push_back(j+1);
return res;
}
else if(nums[i]+nums[j] < target)
i++;
else
j--;
}
}
};