剑指Offer: 和为S的连续正数序列
题目描述
输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。
例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8。
样例
输入:15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
算法 双指针
设置两个指针 i 和 j ,分别指向连续正数序列的起始和终止
用Sn表示当前连续正数序列的和
以 j 递增的方式遍历整个序列(1到n), 这里可以优化下只需要遍历中间节点的下一个就可以了。 代表查找以 i开头 的时候 结尾j 应该是多少。当Sn < sum说明 j 应该往后移动,当 Sn=sum 说明满足题意,当 Sn > sum 说明向后走即可。
时空分析
时间复杂度: O(n)
C++ 代码
class Solution {
public:
vector<vector<int> > findContinuousSequence(int sum) {
vector<vector<int> > res;
vector<int> path;
int Sn = 0;
for(int i=1, j=2; j <= sum/2+1; ) {
Sn = (i + j)*(j - i + 1)/2;
if (Sn == sum) {
int k = i;
while(k <= j) {
path.push_back(k);
k++;
}
res.push_back(path);
path.clear();
i++;
j++;
}
else if (Sn > sum)
i++;
else if (Sn < sum)
j++;
}
return res;
}
};
第一版写的程序:
class Solution {
public:
vector<vector<int> > findContinuousSequence(int sum) {
vector<vector<int> > res;
vector<int> cres;
if (sum < 3)
return res;
int i = 1, j = 1;
int Sn = 0;
while(i <= sum/2+1)
{
Sn += i;
while (Sn > sum)
{
Sn -= j;
j++;
}
if (Sn == sum)
{
cres.clear();
for(int index = j; index <= i; index++)
cres.push_back(index);
res.push_back(cres);
}
i++;
}
return res;
}
};