问题1:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
思路:两个指针,由于是排序数组,初始时分别指向头和尾。
如果指针指向的两个数的和大于s,则j减一;小于s,i加一;等于s,则返回结果。
循环结束条件i>=j。
代码:
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int>& nums, int target) {
int len=nums.size();
vector<int> res;
if(len==1)
return res;
for(int i=0,j=len-1;i<j;)
{
if(nums[i]+nums[j]>target)
j--;
else if(nums[i]+nums[j]<target)
i++;
else
{
res.emplace_back(nums[i]);
res.emplace_back(nums[j]);
break;
}
}
return res;
}
};
复杂度分析:时间复杂度为O(n),空间复杂度为O(1).
问题2:输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
思路:设定序列范围左边界为i,右边界为j。初始化i为1,j为2.
如果当前i与j之间的和大于sum,则i加一。
如果当前i与j之间的和小于sum,则j加一。
如果当前i与j之间的和等于sum,则将i与j之间的序列存储起来。j加一,继续寻找下一个满足条件的序列。
循环条件:i小于j,i小于(sum+1)/2。
技巧:每次加减边界计算序列和,节省时间。
代码:
class Solution {
public:
vector<vector<int>> FindContinuousSequence(int sum) {
vector<vector<int>> res;
if(sum<3)
return res;
int curSum=0;
int i=1;
curSum+=i;
int j=2;
curSum+=j;
while(i<j&&i<(sum+1)/2)
{
if(curSum<sum)
{
j++;
curSum+=j;
}
else if(curSum>sum)
{
curSum-=i;
i++;
}
else
{
vector<int> s;
for(int k=i;k<=j;k++)
{
s.emplace_back(k);
}
res.emplace_back(s);
j++;
curSum+=j;
}
}
return res;
}
};
复杂度分析:时间复杂度为O(n),空间复杂度为O(n)。