这道题是比较典型的滑动窗口,它的整体思想可以参考这篇文章,个人认为是非常值得一看的。
class Solution(object):
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
if len(t) > len(s): #长度更短,直接返回。
return ""
#直接使用Counter对象,自动创建hash
letter_hash = collections.Counter(t) #直接用它来存储每个字母还需要多少个,非常妙。因为来了新的直接减,发现小于0则说明不需要了,不需要额外去加一个字典来作比较。
#剩下的待覆盖的字母数目
num_rest = len(t) #额外用一个数字来看是否满足,也非常妙,不需要逐个value去检查。
#滑动窗口的左右指针
left = 0
right = 0
#最后子串的长度,以及左右边界
min_len = 100000
min_left = -1
min_right = -1
for right in range(len(s)): #右指针滑动
right_chr = s[right]
if right_chr in t: #当前字符在t中
if letter_hash[right_chr] > 0: #对当前字符还有需求
num_rest -= 1
letter_hash[s[right]] -= 1
while num_rest == 0: #此时t的所有字符均被覆盖
if num_rest == 0 and min_len > right - left + 1: #当前子串长度小于最小串长度
min_len = right - left + 1
min_left, min_right = left, right
left_chr = s[left]
if left_chr in t and letter_hash[left_chr] < 0: #当前字符在t中,且滑动后仍满足被完全覆盖(即当前哈希表中left_chr中对应值小于0)
left += 1
letter_hash[left_chr] += 1
elif left_chr not in t:
left += 1 #当前字符不在t中,直接滑走
else: #此时,若再滑动会无法完全覆盖。
break
if min_left == -1:
return ""
return s[min_left: min_right + 1]