滑动窗口是怎么用的
滑动窗口在数组和字符串题里很常见,尤其是要处理'连续区间'时。它的思路不复杂:维护一段区间,右边先扩,再看条件要不要收,左边跟着缩。真正麻烦的地方不在写法,而在于你得先把题目改写成'窗口里要满足什么条件'。
常见的操作就这几步:
- 右指针进窗口,先把新元素算进去。
- 判断当前窗口是否满足题意。
- 满足时更新答案,能缩就缩。
- 不满足时继续扩,直到条件恢复。
这套写法看起来朴素,但很多题一旦改成窗口问题,复杂度会从 (O(n^2)) 直接降到 (O(n))。
几道典型题
长度最小的子数组
题目描述
给定一个含有 n 个正整数的数组和一个正整数 target。
找出该数组中满足其总和大于等于 target 的长度最小的 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4]
输出:1
提示:
1 <= target <= 10^91 <= nums.length <= 10^51 <= nums[i] <= 10^4
实现思路
这题是标准的滑动窗口。暴力枚举子数组会超时,前缀和加二分也能做,但写起来更绕。因为数组里的数全是正整数,窗口右移时和只会变大,左移时和只会变小,这就很适合双指针。
做法很直接:右指针不断加入元素;一旦窗口和达到 target,就尝试缩小左边界,顺手更新最短长度。能继续缩就继续缩,别急着停,最短答案往往就在这里冒出来。
实现代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int n = nums.(), sum = , len = INT_MAX;
( left = , right = ; right < n; right++) {
sum += nums[right];
(sum >= target) {
len = (len, right - left + );
sum -= nums[left++];
}
}
len == INT_MAX ? : len;
}
};


