滑动窗口 解题模板

适用场景

子数组/子串的连续性约束问题(最大/最小/包含/覆盖)

通用模板

可变窗口(求最大/最小)

 
# 求满足条件的最大窗口
 
l = 0
 
for r in range(len(s)):
 
    add(s[r])                # 窗口右扩
 
    while not valid():       # 窗口违规时
 
        remove(s[l])         # 左缩
 
        l += 1
 
    update_answer()          # 更新结果
 
# 求满足条件的最小窗口(标准套模板)
 
need = collections.Counter(t)
 
need_cnt = len(t)
 
l = 0
 
for r, c in enumerate(s):
 
    if c in need:
 
        need[c] -= 1
 
        if need[c] >= 0: need_cnt -= 1
 
    while need_cnt == 0:      # 窗口已覆盖
 
        update_answer()
 
        if s[l] in need:
 
            need[s[l]] += 1
 
            if need[s[l]] > 0: need_cnt += 1
 
        l += 1
 

固定窗口

 
window = [0]*26  # 频次数组
 
for i, c in enumerate(s):
 
    window[ord(c)-97] += 1
 
    if i >= k:
 
        window[ord(s[i-k])-97] -= 1
 
    if window == target:  # 频次匹配
 
        res.append(i-k+1)
 

复杂度总结

模式时间空间典型题
可变窗口O(n)O(k)无重复子串、最小覆盖子串
固定窗口O(n)O(1)异位词、排列
单调队列O(n)O(k)滑动窗口最大值

关键要点

  • 可变窗口模板:右移→缩左→更新

  • 固定窗口模板:加新→去旧→比较

  • 什么时候用 while 缩左?什么时候用 if?

  • 欠账计数(need_cnt)比 Counter 比较更高效

→ 查看该分类题目:LeetCode学习路线图 > 九、滑动窗口


关联题型

关联题型常见结合方式典型题目
数组与哈希哈希表维护窗口状态3无重复字符最长子串
字符串子串问题 + 字符计数76最小覆盖子串
二分查找窗口大小二分枚举209长度最小子数组