题. 和为S的连续正数序列
输入一个非负整数 S,打印出所有和为 S 的连续正数序列(至少含有两个数)。
例如输入 15,由于 1+2+3+4+5=4+5+6=7+8=15,所以结果打印出 3 个连续序列 1∼5、4∼6 和 7∼8。
数据范围
0≤S≤1000
样例
输入:15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
【题解】--- 双指针
双指针算法最核心的用途就是优化时间复杂度。
【核心思想】:
原本两个指针是有 种组合,因此时间复杂度是 。
而双指针算法就是运用单调性使得指针只能单向移动,因此总的时间复杂度只有 ,也就是。
之所以双指针可以实现 的时间复杂度是因为指针只能单向移动,没有指针的回溯,而且每一步都会有指针移动。
而朴素的 算法的问题就在于指针经常回溯到之前的位置。
本题设置两个指针 i
和j
,分别指向连续正数序列的起始和终止;
用s表示当前连续正数序列的和,即s=i+(i+1)+…+j
;
以i递增的方式遍历整个序列(1到n),代表查找以i开头的时候结尾j应该是多少。当s<sums
说明j应该往后移动,当s=sums
说明满足题意,当s>sums
说明向后走即可。
注意上述遍历过程中,s=sums
的情况下不需要把j往前移动,原因是当进入下一个循环前s−=i
,即(i+1)到j的和肯定小于sum。
复杂度分析:
时间复杂度是O(n^2)。
C++代码实现:
class Solution {
public:
vector<vector<int> > findContinuousSequence(int sum) {
vector<vector<int>> res;
for (int i = 1, j = 1, s = 1; i <= sum; i ++ )
{
while (s < sum) j ++, s += j;
if (s == sum && j > i)
{
vector<int> line;
for (int k = i; k <= j; k ++ ) line.push_back(k);
res.push_back(line);
}
s -= i;
}
return res;
}
};