题目重述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
我的思路与代码:
可能最原始的思路,但是我做了优化之后感觉和剑指offer上思路的时间复杂度空间复杂度区别不大,复杂度高在了加起来不等于S 我依然用了循环和res.push_back。欢迎大家给与评论。
思路:
首先我们明白比如数字是100,那么连续序列肯定不会超过50= 100/2;又比如数字99那么连续相加序列也不会超过50= 99/2+1。这里我们为了不去区分奇偶数,都认为和为S的连续正数序列最多不超过 S/2+1,假设连续序列和是tmp;
tmp>sum 时给i++;
tmp<sum 时给j++
例如 S=5
[ 1 2 3 4 5]
相加等于5的连续序列的最大值不超过5/2+1=3;下来开始循环
当tmp<5时,res都会push_back i和j;当tmp>5时,res会清空;当tmp==5时,result.push_back(res),且对res清空处理并break。
i=1
tmp=i=1<5 那么 tmp=tmp+j=1+2=3<5 那么tmp=tmp+j=1+2+3=6>5 break;
i=2
tmp=2<5 那么 tmp=2+3=5 result.push_back(res),且对res清空处理并break;
i=3
tmp=i=3 但是j=i+1=4>(5/2+1) 因此退出循环,return result。
代码
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
int len = sum / 2 +1;
vector<vector<int> > result;
vector<int>res;
if (sum <3) {
return result;
}
else{
for (int i = 1; i <= len; i++) {
int tmp = i;
res.push_back(i);
for (int j = i+1; j <= len; j++) {
if(tmp<sum){
tmp += j;
res.push_back(j);
}
if (tmp > sum) {
res.clear();
break;
}
if (tmp ==sum){
result.push_back(res);
res.clear();
break;
}
}
}
}
return result;
}
};
剑指offer思路
双指针问题
当总和小于sum,大指针继续++
否则小指针++
链接:https://www.nowcoder.com/questionTerminal/c451a3fd84b64cb19485dad758a55ebe?f=discussion
来源:牛客网
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > result;
vector<int> res;
int phigh = 2, plow = 1;
while (phigh > plow) {
int cur = (phigh + plow) * (phigh - plow + 1) / 2;//等差数列求和
if (cur < sum)
phigh++;
if (cur == sum) {
for (int i = plow; i <= phigh; i++)
res.push_back(i);
result.push_back(res);
res.clear();
plow++;
}
if (cur > sum)
plow++;
}
return result;
}
};