题目一:和为s的两个数字
输入一个递增排序的数组和一个数字,在数组中查找两个数,使得他们的和正好是s,如果有多对数字的和等于s,则输出任意一对即可。
链接:
剑指Offer(第2版):P280
思路标签:
- 算法:双指针
解答:
- 需要注意题目中给出的条件:递增排序数组。要利用数组排序的性质;
- 使用两个指针,一个指针指向数组的第一个元素,一个数组指向最后一个元素;
- 如果二者的和小于目标和,小指针向前移动;如果二者的和大于目标和,则大指针向后移动。
- 算法是基于递增的性质,如果不是递增则使用hash表来解决。
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
vector<int> result;
int length = array.size();
if(length <= 0)
return result;
int start = 0;
int end = length - 1;
while(start < end){
int curSum = array[start] + array[end];
if(curSum == sum){
result.push_back(array[start]);
result.push_back(array[end]);
break;
}
else if(curSum > sum)
end--;
else
start++;
}
return result;
}
};
题目二:和为s的连续正数序列
输入一个正数s,输出所有和为s的连续正数序列(至少含有两个数)。
例子:
输入15,由于1+2+3+4+5=4+5+6=4+5+6=7+8=15,所以打印出3个连续序列1~5、4~6和7~8.
链接:
剑指Offer(第2版):P282
思路标签:
- 算法:双指针
解答:
- 还是以上面类似的思路,使用双指针来解决;
- 小指针初始为1,大指针初始为2;
- 如果从小到大的数字的和大于目标和,则抛弃小指针当前值,也就是小指针加1;如果从小到大数字的和小于目标和,则增加大指针;
- 注意循环的边界条件:samll
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > ret;
if(sum < 3)
return ret;
int small = 1;
int big = 2;
int middle = (1+sum)/2;
int curSum = small + big;
while(small < middle && big < sum){
while(curSum > sum){
curSum -= small;
small++;
}
if(curSum == sum)
InsertRet(small, big, ret);
big++;
curSum += big;
}
return ret;
}
void InsertRet(int small, int big, vector<vector<int> > &ret){
vector<int> temp;
for(int i=small; i<=big; ++i)
temp.push_back(i);
ret.push_back(temp);
return;
}
};