算法笔记:滑动窗口
滑动窗口通用模板
1 | std::unordered_map<char, int> need, window; |
关键点说明
1️⃣ 窗口收缩条件(最重要的区别)
不同题目的收缩条件不同:
| 题目类型 | 收缩条件 | 何时更新结果 |
|---|---|---|
| 最小覆盖子串 | valid == need.size() |
收缩时(找最小) |
| 字符串排列 | right - left >= target.size() |
收缩时(固定长度) |
| 找所有异位词 | right - left >= target.size() |
收缩时(固定长度) |
| 最长无重复子串 | window[c] > 1(有重复) |
扩张时(找最大) |
2️⃣ 何时更新结果
1 | // 情况1:求最小 → 在收缩窗口时更新 |
三道经典题对比
🔹 最小覆盖子串 (LeetCode 76)
1 | while (valid == need.size()) { // 包含所有字符时收缩 |
🔹 字符串排列 (LeetCode 567)
1 | while (right - left >= s1.size()) { // 窗口达到目标长度时收缩 |
🔹 找所有异位词 (LeetCode 438)
1 | while (right - left >= p.size()) { |
核心思想
Note
基于这个框架,遇到子串/子数组相关的题目,只需要回答以下三个问题:
1、什么时候应该移动 right 扩大窗口?窗口加入字符时,应该更新哪些数据?
2、什么时候窗口应该暂停扩大,开始移动 left 缩小窗口?从窗口移出字符时,应该更新哪些数据?
3、什么时候应该更新结果?
- 右指针扩张:不断纳入新元素
- 左指针收缩:满足条件时尝试优化
- valid 计数:追踪匹配状态
- 灵活调整:根据题目需求调整收缩条件和结果更新时机
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 逸人の博客!
评论

