·题目描述
给你一个字符串 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 Falsereturn Truedef 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] = 0star = 0res = ""minlength = float('inf')for end in range(len(s)):if s[end] in need:char_map[s[end]] += 1end += 1while self.isContains(char_map,need):curlength = end - star + 1if curlength < minlength:minlength = curlengthres = s[star: end+1]if s[star] in need:char_map[s[star]] -= 1star -= 1return 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] = 0min_star ,min_end = 0,0min_length = float('inf')target_num = len(t)star = 0for end in range(len(s)):if s[end] in need:windows[s[end]] += 1if windows[s[end]] <= need[s[end]]:target_num -= 1while target_num == 0:cur_length = end - star + 1if cur_length < min_length:min_length = cur_lengthmin_star = starmin_end = endif s[star] in need:windows[s[star]] -= 1if windows[s[star]] < need[s[star]]:target_num += 1star += 1if 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]] -= 1if windows[s[star]] < need[s[star]]:target_num += 1
结束时候的判断条件就变为了,windows[s[star]] >= need[s[star]],这是因为,移动左窗口的时候,会导致所需要的元素滑出,从而影响所需要的target_num