滑动窗口适合解决要求连续子数组且涉及最大/最小或满足某条件的最短/最长长度的问题,如和≥target的最短子数组、无重复字符的最长子串、滑动窗口最大值等。

滑动窗口适合解决哪类数组问题
当题目要求「连续子数组」且涉及「最大/最小/满足某条件的最短/最长长度」时,滑动窗口是首选。比如找和 ≥ target 的最短子数组、无重复字符的最长子串(转为数组索引处理)、窗口内最大值(配合单调队列)等。它本质是用两个指针维护一个动态区间,避免暴力 O(n²) 枚举所有子数组。
while 循环里先移动右指针还是左指针
标准写法是:外层 for 或 while 控制右指针 r 扩展,内层 while 在满足收缩条件时移动左指针 l。关键在于「收缩条件」必须明确——通常是当前窗口已满足目标(如和 ≥ target),才尝试缩窗以找更优解。
常见错误是把收缩逻辑写在右指针循环外,或混淆判断时机。例如求最小长度子数组:
int l = 0, sum = 0, minLen = INT_MAX;
for (int r = 0; r < nums.size(); r++) {
sum += nums[r];
while (sum >= target) { // 满足条件才缩窗
minLen = min(minLen, r - l + 1);
sum -= nums[l++];
}
}注意:sum 必须在 l++ 前减去 nums[l],否则会漏减或越界。
立即学习“C++免费学习笔记(深入)”;
如何处理窗口内最大/最小值更新
如果题目要求每个窗口的最大值(如 maxSlidingWindow),不能每次遍历窗口找极值(O(k) 耗时),得用单调队列。核心是维护一个双端队列 deque<int>,存索引,保证队首始终是当前窗口最大值的下标。
操作要点:
- 入队前,从队尾弹出所有
< nums[i]的元素(维持递减) - 检查队首索引是否已滑出窗口(
< l),是则弹出 - 队首即为当前窗口最大值对应索引
容易忽略的是:队列存的是下标而非值,这样才能判断是否过期;且每次移动窗口都要做清理,不只在右指针扩展时。
边界与初始化最容易错的三个点
滑动窗口代码看似简单,但生产环境常因边界挂掉:
- 初始
l和r都设为 0,但有些题需l=0, r=-1表示空窗,避免首次加数逻辑混乱 - 返回值没覆盖无解情况:如没找到满足条件的子数组,应返回 0 或 -1,但常忘记判断
minLen是否仍为INT_MAX - 数据类型溢出:累加和用
int可能溢出,尤其数组值大或长,改用long long更稳妥
真正难的不是写对模板,而是根据题干精确建模「窗口代表什么」「何时扩张」「何时收缩」「何时更新答案」——这几个判断点稍一模糊,整个逻辑就偏了。


















