滑动窗口:双指针背后的不变量

窗口题看起来多,骨架却相似:维护合法区间,并在扩张与收缩间切换。

滑动窗口是双指针在序列上的特化。关键不是背模板,而是写清:窗口内统计量代表什么,以及何时右扩、何时左缩。

通用骨架

func sliding(s string) int {
    left := 0
    best := 0
    // window 统计结构
    for right := 0; right < len(s); right++ {
        // 1. 纳入 s[right]
        for /* 窗口不合法 */ {
            // 2. 剔除 s[left]; left++
        }
        // 3. 用合法窗口更新答案
        best = max(best, right-left+1)
    }
    return best
}

两类典型

  • 最长合法:尽量扩张,不合法才收缩(如无重复字符最长子串)。
  • 最短合法:一合法就尝试收缩,记录最小长度(如最小覆盖子串)。

易错点

计数归零时要从 map 删除还是留 0;「恰好 K」与「最多 K」的条件差一个等号。先写不变量注释,再改代码。

小结

把题目翻译成「窗口合法条件」,模板自然落地。调试时打印 left、right 与统计量,比空想边界更快。