·题目描述
给你一个字符串 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 的子串中,
因此没有符合条件的子字符串,返回空字符串。
·解题思路:
1.需要字符类型和个数——考虑创建字典
创建两个字典,一个用于存放目标所需要的字母和个数;一个用来记录滑动窗口所涉及的字母和个数
2.需要记录窗口的起始——考虑滑动窗口
先滑动end,即窗口的右端,遍历记录字符。当满足所需要求的时候,再考虑滑动窗口的左端,缩短窗口长度,获取最小窗口
3.循环判断条件:
当滑动窗口包含目标窗口的时候,进入循环条件,移动左端指针。
·代码:
class Solution:
def isContains(self,cur_str,target_str):
for key in target_str:
if cur_str[key] < target_str[key]:
return False
return True
def minWindow(self, s: str, t: str) -> str:
need = Counter(t)
char_map = {}
for key in need :
if key not in char_map:
char_map[key] = 0
star = 0
res = ""
minlength = float('inf')
for end in range(len(s)):
if s[end] in need:
char_map[s[end]] += 1
end += 1
while self.isContains(char_map,need):
curlength = end - star + 1
if curlength < minlength:
minlength = curlength
res = s[star: end+1]
if s[star] in need:
char_map[s[star]] -= 1
star -= 1
return res
·代码优化
每次切片存储并且使用额外函数判断循环条件过于麻烦,考虑使用target_num对所需字符串个数进行计数。
def minWindow(self, s: str, t: str) -> str:
need ,windows = Counter(t),{}
for key in need :
if key not in windows:
windows[key] = 0
min_star ,min_end = 0,0
min_length = float('inf')
target_num = len(t)
star = 0
for end in range(len(s)):
if s[end] in need:
windows[s[end]] += 1
if windows[s[end]] <= need[s[end]]:
target_num -= 1
while target_num == 0:
cur_length = end - star + 1
if cur_length < min_length:
min_length = cur_length
min_star = star
min_end = end
if s[star] in need:
windows[s[star]] -= 1
if windows[s[star]] < need[s[star]]:
target_num += 1
star += 1
if min_length == float('inf'):
return ''
return s[min_star : min_end+1]
————两个注意的点————
if windows[s[end]] <= need[s[end]]:
target_num -= 1
这里表示,当滑动窗口中字符个数小于或等于所需要个数的时候,所需要的target_num 减一。这是因为该语句end] in need的条件下,也就是说,现在所放入的是s[end]一定是need中的字符,所以num可以减一。
若是改为windows[s[end]] >= need[s[end]],就会出现因为多余字符导致target_num 减为0 的情况。
if s[star] in need:
windows[s[star]] -= 1
if windows[s[star]] < need[s[star]]:
target_num += 1
结束时候的判断条件就变为了,windows[s[star]] >= need[s[star]],这是因为,移动左窗口的时候,会导致所需要的元素滑出,从而影响所需要的target_num