滑动窗口框架
套路纲数组与双指针什么时候想到它(适用信号)
- 求"连续子串 / 子数组"的最长、最短、是否包含
- 暴力解法需要枚举所有区间(两层循环 O(n²))
- 区间的合法性可以增量判断(加入/移出一个元素就能判定)
一句话核心
右指针负责扩张、左指针负责收缩,每个元素进窗口一次、出窗口一次——把"枚举所有区间"压缩成 O(n)。
通用模板(先背骨架)
js1function slidingWindow(s) {
2 let left = 0;
3 let best = 0;
4 const window = new Map(); // 窗口内的统计量
5 for (let right = 0; right < s.length; right++) {
6 // 1) 扩窗:把 s[right] 加入统计
7 window.set(s[right], (window.get(s[right]) ?? 0) + 1);
8 while (窗口不合法(window)) {
9 // 2) 缩窗:把 s[left] 移出统计
10 window.set(s[left], window.get(s[left]) - 1);
11 left += 1;
12 }
13 // 3) 更新答案(此刻窗口合法)
14 best = Math.max(best, right - left + 1);
15 }
16 return best;
17}
关键问题清单(做题时按顺序回答,把模板套进去)
- 何时扩窗?——通常每个 right 都无条件扩
- 何时缩窗?——窗口"不合法"时,用 while 而不是 if(可能要连续缩多次)
- 何时更新答案?——缩窗结束、窗口合法的那一刻(这个时机放错是答案偏差的常见原因)
- 窗口需要维护什么统计量?——频次表 / 和 / 不同字符数
常见坑
- 缩窗用 if 而不是 while——一次可能需要移出多个元素才恢复合法
- 窗口长度是 right - left + 1,别写成 right - left
- 更新答案是"扩窗后立刻"还是"缩窗后"?先想清楚本题要求的窗口是哪种状态