题目
题目描述
给你一个字符串 s 、一个字符串 t 。返回 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 是最小覆盖子串。
示例 3:
输入: s = “a”, t = “aa”
输出: “”
解释: t 中两个字符 ‘a’ 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
提示:
m == s.length
n == t.length
1 <= m, n <=
1
0
5
10^5
105
s 和 t 由英文字母组成
进阶:你能设计一个在 o(m+n) 时间内解决此问题的算法吗?
题解
要解决这个问题,我们可以使用滑动窗口技术。这个方法可以在 O(m + n) 的时间复杂度内解决问题,其中 m 是字符串 s 的长度,n 是字符串 t 的长度。
以下是解题步骤:
- 创建两个字典:一个用于记录目标字符串 t 中每个字符的出现次数(
need),另一个用于记录当前窗口中包含的 t 中字符的数量(window)。 - 初始化左右指针
left和right都指向字符串 s 的起始位置,并且初始化一个变量valid用来记录窗口中满足need条件的字符个数。 - 开始扩大右边界
right,直到窗口包含了 t 的所有字符:- 如果
right指向的字符是need中需要的字符,则更新window字典和valid变量。
- 如果
- 当窗口已经包含了 t 的所有字符时,开始收缩左边界
left,以找到更小的覆盖子串:- 在收缩之前,检查是否可以更新最小覆盖子串。
- 如果
left指向的字符是need中需要的字符,在收缩后更新window字典和valid变量。
- 重复上述过程,直到
right到达字符串 s 的末尾。 - 返回最小覆盖子串的结果。
下面是 Python 实现代码:
from collections import defaultdict
def min_window(s, t):
need, window = defaultdict(int), defaultdict(int)
for c in t:
need[c] += 1
left, right = 0, 0
valid = 0
start, length = 0, float('inf')
while right < len(s):
# 扩大窗口
c = s[right]
right += 1
if c in need:
window[c] += 1
if window[c] == need[c]:
valid += 1
# 收缩窗口
while valid == len(need):
if right - left < length:
start = left
length = right - left
d = s[left]
left += 1
if d in need:
if window[d] == need[d]:
valid -= 1
window[d] -= 1
return "" if length == float('inf') else s[start:start+length]
这段代码实现了滑动窗口算法来查找最小覆盖子串。它通过调整窗口大小来确保窗口内的字符串包含了 t 中的所有字符,并且尽可能短。
提交结果


817

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



