LeetCode 76. 最小覆盖子串
题目地址(76. 最小覆盖子串)
题目描述
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
示例 2:
输入:s = "a", t = "a"
输出:"a"
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
提示:
1 <= s.length, t.length <= 105
s 和 t 由英文字母组成
进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?
思路
滑动窗口,右边扩张,满足字符串遍历条件后,左边收缩,难点在于左边收缩的边界条件
代码
- 语言支持:Python3
Python3 Code:
class Solution:
def minWindow(self, s: str, t: str) -> str:
from collections import Counter
length = len(s)
left,right,match = 0, 0,0
resLeft,resRight,minResLen = 0, 0,length+1
tDict = Counter(t)
while right < length:
#先右边扩张
# print(left, right, resLeft, resRight)
# print([s[left:right+1]])
rS = s[right]
# print(rS,tDict)
if rS in tDict:
tDict[rS] -= 1
if tDict[rS] >= 0:
match += 1
#收缩条件
while match == len(t):
#判断是否最短子串长度
if (right - left) < minResLen:
# print([s[left:right + 1]],resRight,resLeft, minResLen)
minResLen = min(minResLen,right-left)
resLeft,resRight = left,right
#左边在收缩,直到mtath<len(t)
if left <= right:
lS = s[left]
if lS in tDict:
tDict[lS] += 1
if tDict[lS] > 0:
match -= 1
# print(lS, tDict)
left += 1
right += 1
# print(left, right, resLeft, resRight)
return s[resLeft:resRight+1] if minResLen != length+1 else ""
if __name__ == '__main__':
s = "ADOBECODEBANC"
t = "ABC"
s = "a"
t = "a"
result = Solution().minWindow(s,t)
print(result)
复杂度分析
令 n 为数组长度。
- 时间复杂度:O(n)O(n)O(n)
- 空间复杂度:O(n)O(n)O(n)
转载自:https://juejin.cn/post/7022816739331145742