“Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
输入: target = 9
输出: [[2,3,4],[4,5]]
示例2:
输入: target = 15
输出: [[1,2,3,4,5],[4,5,6],[7,8]]
二、思路分析:
这是一个明显的滑动窗口题目,而且题目要求了滑动窗口的最小宽度为2.
那什么是滑动窗口那?我们借用题解中的一个图来解释一下滑动窗口。
上图所示的黄色框就是滑动窗口,滑动窗口的题目一般有两种:定长窗口和不定长窗口,本题目不限制长度,因此是不定长窗口。滑动窗口圈定了一连串数字,我们计算这串数字的和是否满足target,如果不满足,我们可以通过移动左端点和右端点来调整窗口。
滑动窗口使用要具备一个重要性质: 窗口的左边界和右边界永远只能向右移动,而不能向左移动。
使用滑动窗口的核心在于寻找到如何扩大窗口和缩小窗口的方案
- 当窗口内元素和小于target时,此时需要扩大窗口,有边界右移
- 当窗口内元素和小于target时,此时需要缩小窗口,左边界右移
- 当窗口的元素和恰好等于 target 的时候,记录此时的结果,然后左边界右移
为什么第三种情况是移动左边界那?因为以当前左边界为起点的窗口和等于target只有一种情况。
三、AC 代码:
var findContinuousSequence = function(target) {
let left = 1;
let right = 1;
let sum = 0;
const result = [];
while(left <= target / 2) {
// 当窗口内元素和小于target时,此时需要扩大窗口,有边界右移
if(sum < target) {
sum += right;
right ++;
} else if(sum > target) {
// 当窗口内元素和小于target时,此时需要缩小窗口,左边界右移
sum -= left;
left ++;
} else {
// 当窗口的元素和恰好等于 target 的时候,记录此时的结果,然后左边界右移
let cnt = [];
for(let i = left; i < right; i++) {
cnt.push(i);
}
result.push(cnt);
sum -= left;
left ++;
}
}
return result;
};
四、总结:
滑动窗口的思想其实是非常类似于双指针的,主要性质在于窗口的左边界和右边界永远只能向右移动,而不能向左移动。主要核心在于找到窗口扩展及缩小的方案