给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
- 对于
t中重复字符,我们寻找的子字符串中该字符数量必须不少于t中该字符数量。 - 如果
s中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入: s = "ADOBECODEBANC", t = "ABC"
输出: "BANC"
解释: 最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
class Solution:
def minWindow(self, s: str, t: str) -> str:
if len(s) < len(t):
return ""
# 定义哈希表,用于记录窗口内字符和目标字符串字符
dic_s=defaultdict(int)
dic_t=defaultdict(int)
# 初始化目标字符串的哈希表
for i in t:
dic_t[i]+=1
# 定义滑动窗口的起始和结束
start, end = 0, 0
min_len = float('inf')
min_start = 0
have = 0
total = len(t)
# 滑动窗口进行遍历
while end < len(s):
# 扩大窗口,添加字符到哈希表中
char_end = s[end]
dic_s[char_end] += 1
# 如果当前字符满足了目标字符的数量,增加已满足的数量
if char_end in dic_t and dic_s[char_end]<=dic_t[char_end]:
have+=1
# 当所有字符都满足时,尝试缩小窗口
while have == total:
# 更新最小窗口
if end - start + 1 < min_len:
min_len = end - start + 1
min_start = start
# 尝试缩小窗口,从左边移动
char_start = s[start]
dic_s[char_start] -= 1
if dic_start in dic_t and dic_s[char_start] < dic_t[char_start]:
have -= 1
start += 1
# 移动窗口的右端
end += 1
# 返回最小覆盖子串
if min_len == float('inf'):
return ""
else:
return s[min_start:min_start + min_len]
```js
代码思路
-
初始化:
- 定义两个哈希表
dic_s和dic_t,分别用来存储滑动窗口内的字符频率和目标字符串t中的字符频率。 - 初始化滑动窗口的左右指针
start和end,以及用于记录最小窗口长度和起始位置的min_len和min_start。 - 初始化
have变量来记录窗口中已经满足t中字符要求的数量,total变量来记录t中字符的总种类数。
- 定义两个哈希表
-
滑动窗口:
- 使用
while循环,通过移动窗口的右端end来遍历字符串s。 - 每次循环,将
end指向的字符加入到dic_s中,并更新其计数。 - 如果
end指向的字符在dic_t中,并且dic_s中该字符的计数不超过dic_t中的计数,则have加1,表示找到了一个满足条件的字符。
- 使用
-
缩小窗口:
- 当
have等于total,即窗口中包含了t中所有种类的字符时,尝试缩小窗口。 - 检查是否可以从窗口的左端
start移除字符,即检查start指向的字符是否仍然满足条件(即dic_s中该字符的计数是否小于dic_t中的计数)。 - 如果不满足,则
have减1,表示移除了一个满足条件的字符。 - 如果满足条件,则更新最小窗口的长度和起始位置。
- 当
-
更新最小窗口:
- 在尝试缩小窗口的过程中,如果发现了一个更小的窗口,则更新
min_len和min_start。
- 在尝试缩小窗口的过程中,如果发现了一个更小的窗口,则更新
-
返回结果:
- 循环结束后,如果找到了符合条件的最小窗口,则返回这个窗口的字符串;如果没有找到,则返回空字符串。