滑动窗口算法专栏导览:从原理到 LeetCode 面试通关
专栏定位
本专栏面向有一定编程基础、正在备战技术面试的工程师。讨论范围严格限定于滑动窗口算法及其直接衍生技法,不涉及动态规划、图算法等其他领域。
目标:帮助读者真正理解滑动窗口的底层逻辑,而非死记硬背套路模板。每道题的讲解遵循”是什么 → 为什么出现 → 不这样会怎样 → 如何落地 → 边界与反例”的推导链,力求通俗易懂而不失深度。
专栏目录
| 序号 | 文章标题 | 核心话题 | 覆盖 LeetCode 题目 |
|---|---|---|---|
| 01 | 滑动窗口算法原理全景:从暴力枚举到 的思维跃迁 | 窗口本质、固定 vs 可变分类、通用模板框架、时间复杂度证明 | 概念篇,无具体题目 |
| 02 | 固定长度滑动窗口:模板推导与三题精讲 | 固定窗口的进/出平衡、Deque 维护极值、字符计数匹配 | 643、1343、567 |
| 03 | 最小覆盖子串:可变窗口收缩条件的黄金法则 | 窗口收缩的触发时机、need/have 双计数器、字符频率维护 | 76、3 |
| 04 | 最长扩张型可变窗口:替换操作与连续性约束 | 替换计数技巧、窗口合法性维护、“不缩反扩”的反直觉优化 | 424、1004、1493 |
| 05 | 同向双指针统一视角:快慢指针与滑动窗口的辩证关系 | 双指针语义映射、链表快慢指针、数组同向指针与窗口的等价变换 | 209、904、2401 |
| 06 | 字符计数窗口:哈希表与滑动窗口的黄金组合 | 固定窗口下的字母异位词、变长窗口下的多词串联、编码效率优化 | 438、30、187 |
| 07 | 单调队列优化滑动窗口: 求窗口极值的艺术 | 单调双端队列原理、队列维护不变量、多种写法对比 | 239、1438、2762 |
| 08 | 前缀和与滑动窗口的思想融合:子数组求和类问题 | 前缀和下标变换、哈希加速查找、窗口与前缀和的适用边界 | 560、974、1248 |
| 09 | 多类别元素与恰好 K 型窗口:高阶滑动窗口技法 | ”恰好 K” = “最多 K” − “最多 K−1”、多类别计数器 | 992、1234、2461 |
| 10 | 滑动窗口综合通关:面试高频模式总结与难题攻破 | 模式识别决策树、算法选型、复杂度速查、高频错误盘点 | 综合复习篇 |
专栏阅读建议
- 第 01 篇必读:透彻理解”窗口”这个抽象概念,后续所有变体才有统一的理解框架
- 固定窗口篇(02、06):先从最简单的情形入手,理解”滑动”的物理含义
- 可变窗口篇(03、04、05):这是难度的核心所在——收缩时机的判断是整个算法的灵魂
- 优化篇(07、08):单调队列和前缀和是对滑动窗口的两个不同维度的增强,建议在理解基础窗口后再看
- 高阶篇(09):“恰好 K”技巧是面试压轴题的常客,属于思维量较大的内容
- 本专栏不覆盖:动态规划(虽然部分题可用 DP 解,但不在本专栏讨论范围内)、树形结构上的窗口操作
核心模板速查
固定窗口通用框架
int left = 0;
// 初始化:先填入前 k 个元素
for (int right = 0; right < k; right++) add(nums[right]);
update(answer);
// 滑动
for (int right = k; right < n; right++) {
add(nums[right]); // 新元素进窗
remove(nums[left++]); // 旧元素出窗
update(answer);
}可变窗口通用框架
int left = 0;
for (int right = 0; right < n; right++) {
add(nums[right]); // 扩展右边界
while (窗口不合法) {
remove(nums[left++]); // 收缩左边界
}
update(answer); // 此时窗口合法,更新答案
}时间复杂度一览
| 题型 | 典型场景 | 时间复杂度 | 空间复杂度 |
|---|---|---|---|
| 固定窗口,维护统计量 | 子数组均值/最大和 | 或 | |
| 固定窗口,维护极值(单调队列) | 滑动窗口最大值 | ||
| 可变窗口,字符计数 | 最小覆盖子串、字母异位词 | ||
| 可变窗口,数值约束 | 最长连续子数组 | ||
| 恰好 K 型转化 | K 个不同整数子数组 | ||
| 前缀和 + 哈希 | 和为 K 的子数组 |