滑动窗口算法核心思路
滑动窗口是处理数组或字符串子串/子数组问题的利器。它的本质是用两个指针维护一个动态区间,通过移动左右边界来扩大或缩小窗口,通常能在一次遍历中完成计算,时间复杂度稳定在 O(n)。
适用场景:寻找最长无重复字符的子串、和为目标值的最短子数组、字符串排列匹配等。
通用模板逻辑
- 定义
left和right指针,初始指向首元素; right向右移动模拟进窗口,更新状态;- 当窗口不满足条件时,
left向右移动模拟出窗口,直到恢复合法; - 过程中根据需求更新结果。
结束条件是 right 越界。下面我们通过四道经典题目来拆解不同场景下的变体。
1. 长度最小的子数组 (LeetCode 209)
问题描述
给定一个含有 n 个正整数的数组和一个正整数 target,找出该数组中满足其和 ≥ target 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
解题思路
因为数组元素均为正整数,求和具有单调性,这非常符合滑动窗口的特性。
- 初始化
left = right = 0,sum = 0。 right不断右移累加sum。- 一旦
sum >= target,说明当前窗口满足条件,尝试收缩左边界(left++)以寻找更短的子数组,同时更新最小长度。 - 注意:收缩过程中只要仍满足条件,就要持续更新结果。
代码实现
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0, right = 0;
int len = INT_MAX, sum = 0;
while(right < nums.size()) {
sum += nums[right]; // 进窗口
while(sum >= target) { // 保证窗口合法
len = min(len, right - left + 1); // 更新结果
sum -= nums[left++]; // 出窗口
}
right++;
}
len == INT_MAX ? : len;
}
};


