字符串处理是算法领域的经典问题类型,其中子串匹配类问题在各大技术面试中出现频率极高。最小覆盖子串(Minimum Window Substring)作为力扣Hot100题库中的高频难题,考察的是在复杂约束条件下对滑动窗口算法的灵活运用。
这道题的典型描述是:给定字符串S和T,要求在S中找到包含T所有字符的最短连续子串。例如S="ADOBECODEBANC",T="ABC"时,正确解应为"BANC"。表面看似简单,实际处理时需要解决几个关键难点:
滑动窗口是处理子串/子数组问题的利器。其核心思想是维护一个可动态伸缩的窗口,通过左右指针的移动来探索解空间。对于本问题,标准滑动窗口需要经过三个阶段:
python复制def minWindow(s: str, t: str) -> str:
from collections import defaultdict
need = defaultdict(int)
for c in t:
need[c] += 1
missing = len(t)
left = start = end = 0
for right, char in enumerate(s, 1):
if need[char] > 0:
missing -= 1
need[char] -= 1
if missing == 0:
while left < right and need[s[left]] < 0:
need[s[left]] += 1
left += 1
if end == 0 or right - left <= end - start:
start, end = left, right
need[s[left]] += 1
missing += 1
left += 1
return s[start:end]
实现时需要两个关键技术组件:
关键变量说明:
need字典:存储T中每个字符还需匹配的次数(可正可负)missing计数器:记录还缺少的字符总数left/right指针:窗口左右边界(左闭右开区间)注意:当
need[char]为负值时,表示该字符在窗口中已超额出现。这在收缩阶段是重要判断依据。
实际编码时需要特别注意几种边界情况:
优化判断逻辑:
python复制if not s or not t or len(s) < len(t):
return ""
基础实现的时间复杂度是O(|S|+|T|),但可以通过以下优化进一步提升:
优化后的滑动窗口示例:
python复制filtered_s = [(i, char) for i, char in enumerate(s) if char in need]
遇到问题时建议按此顺序检查:
调试时可以打印关键变量:
python复制print(f"right={right}, char={char}, need={need}, missing={missing}")
mermaid复制graph TD
A[子串匹配问题] --> B{需要精确匹配?}
B -->|是| C[KMP/Rabin-Karp]
B -->|否| D{需要考虑字符频率?}
D -->|是| E[滑动窗口+哈希表]
D -->|否| F[普通滑动窗口]
这个算法在文本编辑器中的"查找并高亮"功能中有直接应用。当用户搜索多个关键词时,编辑器需要找到包含所有关键词的最小文本范围进行高亮显示。理解滑动窗口的原理可以帮助我们优化这类实时搜索体验。