滑动窗口算法
想象你坐公交车:
- 窗口就是车窗,每前进一站,窗口内的人就发生变化
- 左边的人下车(移除窗口),右边的人上车(加入窗口)
- 始终保持窗口内是一段连续的乘客
这就是滑动窗口的核心思想——维护一个可变区间,在区间滑动的过程中更新答案。
【直观类比】
滑动窗口就像你想在公司附近租一套房子:
- 你设定一个预算范围(窗口大小)
- 从内环向外环开始看房(窗口滑动)
- 发现月租超出预算,就从左边减一个小区(左边界收缩)
- 发现还有空间,从右边加一个小区(右边界扩张)
- 直到找到最合适的为止
这个"看房→调整范围→继续看"的循环,就是滑动窗口的精髓。
一、问题的引入
先看一道经典题:
给定一个数组
nums和一个窗口大小k,求所有窗口的最大值。
示例:
普通解法:O(n*k) — 每个窗口遍历 k 个元素
滑动窗口解法:O(n) — 每个元素只进窗口一次、出窗口一次
二、滑动窗口的两大类型
2.1 固定窗口(窗口大小不变)
模板:
应用场景:求所有窗口的最大值、窗口内元素和等
2.2 变化窗口(窗口大小动态变化)
模板:
应用场景:最短子数组、和大于等于 target 等
三、实战:LeetCode 239 滑动窗口最大值 🔴
题目:
暴力解法(超时):
单调队列优化:O(n)
核心思想:单调队列
四、实战:LeetCode 76 最小覆盖子串 🔴
题目:
示例:
解题思路:
关键点:
- 用
need统计需要匹配的字符 - 用
window统计窗口内的字符 matchCount记录已匹配字符种类数
五、常见题型总结
六、记忆技巧
滑动窗口的三口诀:
"右扩撑满,左缩找最优,再扩再缩,直到遍历完"
固定窗口:for 右边界扩张 → if 窗口满 → 收缩左边界 → 记录答案
变化窗口:for 右边界扩张 → while 满足条件 → 收缩左边界 → 更新答案
七、实战检验
检验一:LeetCode 3 无重复字符的最长子串
检验二:LeetCode 438 找到字符串中所有字母异位词
考点:固定窗口 + 字符计数 + 窗口收缩时机。
八、总结
滑动窗口的核心是双指针的优雅应用:
- 右指针扩张:把新元素加入窗口
- 条件判断:是否满足某种条件
- 左指针收缩:在满足条件时,尝试缩小窗口
- 更新答案:在窗口变化的过程中记录最优解
记住:滑动窗口不是魔法,它是"有策略的双指针"。