#76
Hard
滑动窗口
Minimum Window Substring
找出包含 t 全部字符的最小子串。
找出 s 中包含 t 全部字符且频次也满足要求的最小子串。真正的难点不是找到一个合法窗口,而是在不丢覆盖的前提下把它缩到最短。
StringSliding Window
题目定位
这是最经典的覆盖型窗口:先扩张到完全覆盖,再在仍合法的前提下尽量收缩。
关键观察
核心状态不是简单的不同字符个数,而是“有多少种必需字符的需求频次已经被完全满足”。
目标复杂度
O(n) / O(k)
这题的解法思路怎么拆
1
先为 t 建一个频次表,明确每个字符需要满足多少次。
2
右指针扩张时,把对应字符的需求量减一。
3
当全部需求都满足后,就尽可能右移左指针,把窗口缩到仍然合法的最短状态。
4
每次窗口合法时,都拿它和当前最优答案比较。
拿一个例子顺一遍
1
例如 s = "ADOBECODEBANC", t = "ABC"。
2
第一次找到的合法窗口是 "ADOBEC",但它还不是最短。
3
继续扩张和收缩,直到找到窗口 "BANC"。
4
此时已经不存在更短的合法窗口,所以答案就是 "BANC"。
参考实现
Pythonfrom collections import Counter
def minWindow(s: str, t: str) -> str:
need = Counter(t)
missing = len(t)
left = 0
best_start = 0
best_len = float("inf")
for right, char in enumerate(s):
if need[char] > 0:
missing -= 1
need[char] -= 1
while missing == 0:
if right - left + 1 < best_len:
best_start = left
best_len = right - left + 1
left_char = s[left]
need[left_char] += 1
if need[left_char] > 0:
missing += 1
left += 1
if best_len == float("inf"):
return ""
return s[best_start:best_start + best_len]
常见坑点
warning
把覆盖条件误写成 set 包含,而不是频次满足。
warning
窗口已经失效了还继续收缩。
高频追问
如果题目改成统计合法窗口数量,结构怎么变?
matched 计数器应该在什么时机递减?
继续刷相关题
先把 滑动窗口 这个模式刷成体系,再去做更难变体。