题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序。
解题思路
该题目使用到了等差数列的求和方式和双指针思路。
循环的边界条件:因为题目要求至少包括两个数,那么考虑最少两个数的情况,则较小的一个数不能超过输入数据的1/2,这即是真个最外层循环的终止条件。
题目要求区间起始点小的元素的排在前面,所以应该初始化small为1,big为2。贪心求解的方式如下:
- 求解当前区间的和curSum=curSum = (big + small) * (big - small + 1) / 2
- 如果curSum==sum,那么保存当前区间,整个窗口向后滑动一个单位
- 如果curSum>sum,那么去掉小的元素
- 如果curSum<sum,那么增加一个大的元素
- 如果small超过sum/2,循环终止,因为此时不可能有合理的情况了
更加详细的分析:https://www.nowcoder.com/questionTerminal/c451a3fd84b64cb19485dad758a55ebe
AC代码
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
int small = 1, big = 2;
int curSum = small + big;
vector<vector<int>>res;
while(small <= sum / 2) {
curSum = (big + small) * (big - small + 1) / 2; // 求和
if(curSum == sum) {
vector<int>v;
for(int i = small; i <= big; ++i) {
v.push_back(i);
}
res.push_back(v);
++small; // 在这里区间向后滑动一个
++big;
} else if(curSum > sum) {
curSum -= small;
++small;
} else {
++big;
curSum += big;
}
}
return res;
}
};