题目描述
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例
- 示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]
- 示例 2:
输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
限制
- 1 <= target <= 10^5
解题思路
- code 1 : 暴力枚举。
- code 2 : 滑动窗口
代码
code 1
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
vector< vector<int> > ret;
int i = 1;
int temp, j, k;
while(1){
temp = i;
for(j = 1; temp < target; j++){ // 开始累加
temp += (i + j);
}
if(temp == target){ // 判断累加后的结果是否为 target,是则保存
vector<int> v;
for(k = 0; k < j; k++){
v.push_back(i + k);
}
ret.push_back(v);
}
i++;
if(i > (target/2 + 1)){ // 累加的那串数字的起始位置不能超过 target 的一半,到达此值时,退出循环
break;
}
}
return ret;
}
};
code 2
class Solution {
public:
vector<vector<int>> findContinuousSequence(int target) {
vector< vector<int> > ret;
// left 和 right 定义了滑动窗口的范围为 [left, right)
// 设置窗口只会向右一定移动,即 right 和 left 值只会变大
int left, right;
int temp; // temp 用来记录滑动窗口内数字的和
// 初始化长度为 1 的滑动窗口
left = 1;
right = 2;
temp = 1;
while(1){
if(temp < target){
right++;
temp += (right - 1);
}else if(temp > target){
left++;
temp -= (left - 1);
}else{
vector<int> v;
int i;
for(i = left; i < right; i++){
v.push_back(i);
}
ret.push_back(v);
left++;
right = left + 1;
temp = left;
}
if(left > (target/2 + 1)){
break;
}
}
return ret;
}
};
提交结果
code 1
code 2
总结
- 使用滑动窗口可以使时间复杂度变为O(n)