题目
给你一个字符串
s
、一个字符串t
。返回s
中涵盖t
所有字符的最小子串。如果s
中不存在涵盖t
所有字符的子串,则返回空字符串 ""。
解题
"""
时间复杂度为 O(|S| + |T|),其中 |S| 是字符串 s 的长度,|T| 是字符串 t 的长度
"""
from collections import Counter
def min_window(s: str, t: str) -> str:
# 如果s或t为空,直接返回空字符串
if not s or not t:
return ""
# 统计t中每个字符的频率
dict_t = Counter(t)
# 需要的唯一字符数量
required = len(dict_t)
# 左右指针初始化
left, right = 0, 0
# formed用于记录当前窗口中满足t字符要求的字符数量
formed = 0
# 记录当前窗口中每个字符的频率
window_counts = {}
# 结果元组 (窗口长度, 左指针位置, 右指针位置)
ans = float("inf"), None, None
# 移动右指针扩大窗口
while right < len(s):
# 当前字符
character = s[right]
window_counts[character] = window_counts.get(character, 0) + 1
# 如果当前字符的频率满足t中要求,增加formed计数
if character in dict_t and window_counts[character] == dict_t[character]:
formed += 1
# 当窗口内所有字符频率都满足t的要求时,开始收缩左指针
while left <= right and formed == required:
character = s[left]
# 更新最小窗口
if right - left + 1 < ans[0]:
ans = (right - left + 1, left, right)
# 移出左指针对应的字符
window_counts[character] -= 1
if character in dict_t and window_counts[character] < dict_t[character]:
formed -= 1
# 移动左指针,缩小窗口
left += 1
# 继续移动右指针扩大窗口
right += 1
# 返回最小窗口子串或空字符串
return "" if ans[0] == float("inf") else s[ans[1]:ans[2] + 1]
# 示例
s = "ADOBECODEBANC"
t = "ABC"
result = min_window(s, t)
print(result) # 输出: "BANC"