LeetCode 76. Minimum Window Substring 题解
题目描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果不存在符合条件的子串,则返回空字符串 "" 。
注意:
- 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
示例 2:
输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。
解题思路
使用滑动窗口算法:
- 扩展右边界,直到窗口包含所有需要的字符
- 收缩左边界,找到最小的满足条件的窗口
- 重复直到右边界到达字符串末尾
代码实现
from collections import Counter
def minWindow(s, t):
if not s or not t:
return ""
# 统计t中字符的需求
need = Counter(t)
required = len(need)
# 窗口中的字符统计
window = {}
formed = 0
left = 0
min_len = float('inf')
min_window = ""
for right, char in enumerate(s):
# 扩展窗口
window[char] = window.get(char, 0) + 1
if char in need and window[char] == need[char]:
formed += 1
# 收缩窗口
while formed == required and left <= right:
# 更新最小窗口
if right - left + 1 < min_len:
min_len = right - left + 1
min_window = s[left:right+1]
# 移除左边字符
left_char = s[left]
window[left_char] -= 1
if left_char in need and window[left_char] < need[left_char]:
formed -= 1
left += 1
return min_window
复杂度分析
- 时间复杂度:O(|s| + |t|)
- 空间复杂度:O(|s| + |t|)
优化版本
def minWindow(s, t):
if not s or not t:
return ""
need = [0] * 128
for c in t:
need[ord(c)] += 1
required = len(t)
left = 0
min_len = float('inf')
min_start = 0
for right, c in enumerate(s):
if need[ord(c)] > 0:
required -= 1
need[ord(c)] -= 1
while required == 0:
if right - left + 1 < min_len:
min_len = right - left + 1
min_start = left
left_char = s[left]
need[ord(left_char)] += 1
if need[ord(left_char)] > 0:
required += 1
left += 1
return s[min_start:min_start+min_len] if min_len != float('inf') else ""
测试案例
# 测试案例 1
assert minWindow("ADOBECODEBANC", "ABC") == "BANC"
# 测试案例 2
assert minWindow("a", "a") == "a"
# 测试案例 3
assert minWindow("a", "aa") == ""
总结
本题是滑动窗口算法的经典难题。
关键点:
- 使用哈希表或数组统计字符需求
- 双指针维护滑动窗口
- 在满足条件时收缩窗口找最优解
- 注意重复字符的处理

400

被折叠的 条评论
为什么被折叠?



