[76][困难][滑动窗口] 最小覆盖子串
题目描述
给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
示例:
输入:S = "ADOBECODEBANC", T = "ABC"
输出:"BANC"
提示:
如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。
解题思路
滑动窗口的思路. 定义两个指针, 右指针扩展, 左指针收缩. 在任意时刻, 只移动一个指针. 使用哈希表记录窗口中T
的每个字符出现的次数, 之所以记录次数, 是因为T
中可能有重复的字母.
首先扩展右指针, 直到窗口中包含了所有T
中的所有字符. 然后收缩左指针, 直到抛弃了某个字符后, 窗口不能再覆盖T
中的所有字符.
上面是一个大循环的步骤, 重复这些步骤, 直到右指针越界.

class Solution:
def minWindow(self, s: str, t: str) -> str:
n = len(s)
t_map = Counter(t)
t_set = set(t_map.keys())
t_count = sum(t_map.values())
c_map, c_count = dict(), 0
max_len, res = float('inf'), ''
left = right = 0
while right < n:
c = s[right]
right += 1
if c in t_set:
last_count = c_map.get(c, 0)
if last_count < t_map[c]:
c_count += 1
c_map[c] = c_map.get(c, 0) + 1
if c_count == t_count:
if right - left < max_len:
max_len = right - left
res = s[left: right]
while c_count == t_count:
if right - left < max_len:
max_len = right - left
res = s[left: right]
c = s[left]
left += 1
if c in t_set:
last_count = c_map.get(c, 0)
if last_count <= t_map[c]:
c_count -= 1
c_map[c] = c_map[c] - 1
if c_count < t_count:
break
return res
最后更新于
这有帮助吗?