面试知识库

滑动窗口模板:子串子数组问题的标准武器#

只要题目里出现“连续子串”“连续子数组”“最短”“最长”“满足条件”,滑动窗口就值得你立刻想到。

⚡ 速记版模板#

// 模板用途:维护一个动态区间 [left, right],在 O(n) 内完成连续区间统计
int left = 0; // 窗口左边界,表示当前窗口起点
for (int right = 0; right < s.length(); right++) { // right 逐步右移,扩张窗口
    add(s.charAt(right)); // 把新进入窗口的字符计入状态(频次/计数/和等)
    while (!isValid()) { // 只要窗口不合法,就不断收缩左边界
        remove(s.charAt(left)); // 移出左端字符并同步更新状态
        left++; // 左边界右移,缩小窗口
    }
    updateAnswer(left, right); // 当前窗口合法,尝试更新题目答案
}
java

🎯 什么时候想到滑动窗口?#

典型特征:

  • 处理的是连续区间
  • 需要在线性时间内统计某种性质
  • 左右边界可以逐步移动,而不是每次重新枚举

Hot 100 里的典型题目:

💡 核心思路#

窗口本质上就是维护一个区间 [left, right]:

  • right 负责扩张窗口
  • left 负责收缩窗口
  • 在移动过程中维护窗口内的状态

常见状态包括:

  • 字符频次
  • 元素和
  • 不同字符个数
  • 是否满足某个约束条件

🚀 模板一:最长型窗口#

适合这类问题:

  • 最长无重复子串
  • 最长满足某条件的连续区间

这个模板的关键是:

  • 先扩张
  • 不合法就收缩
  • 合法时更新答案

🚀 模板二:最短型窗口#

适合这类问题:

  • 最短覆盖子串
  • 最短满足条件的连续区间

这个模板的关键是:

  • 先把窗口扩到满足条件
  • 再尽量缩到最短
  • 每次满足条件时都尝试更新答案

🚀 模板三:固定长度窗口#

适合这类问题:

  • 长度固定为 k
  • 每次移动一格做统计

🧠 常见题目怎么套?#

1. 无重复字符的最长子串#

  • 状态:字符出现次数
  • 约束:窗口内每个字符次数都不超过 1
  • 答案:最大长度

2. 最小覆盖子串#

  • 状态:目标字符的需求与当前窗口的覆盖情况
  • 约束:窗口必须覆盖全部需求字符
  • 答案:最短长度

3. 找到所有异位词#

  • 状态:字符频次
  • 窗口长度固定为模式串长度
  • 满足时记录左边界

4. 滑动窗口最大值#

这题本质也是窗口,但通常搭配 单调队列 一起使用。

⚠️ 易错点#

  1. 先更新答案还是先收缩窗口

    • 最长型:通常在合法状态下更新
    • 最短型:通常在满足条件时更新后再收缩
  2. 窗口状态忘记同步删除

    • right 加入了什么,left 移动时就要删除什么
  3. 固定窗口长度判断写错

    • 注意条件是 right - left + 1
  4. 并非所有连续区间题都能用窗口

    • 如果存在负数,某些“和相关”问题就不具备可滑动性
    • 比如 560. 和为 K 的子数组 实际更适合前缀和 + 哈希

🎨 面试时怎么说#

你可以这样说:

我用滑动窗口维护一个连续区间,右指针负责扩张,左指针在条件不满足时收缩,同时维护窗口内的状态信息,从而把暴力枚举的 O(n^2) 优化到 O(n)。

📌 一句话总结#

滑动窗口的本质是:

  • 把“重复枚举区间”变成“增量维护区间”
  • 关键不是窗口本身,而是你维护的状态