给出两个字符串 s 和 t,要求在 s 中找出最短的包含 t 中所有字符的连续子串。
数据范围:,保证s和t字符串中仅包含大小写英文字母
要求:进阶:空间复杂度 , 时间复杂度
例如:
找出的最短子串为.
注意:
如果 s 中没有包含 t 中所有字符的子串,返回空字符串 “”;
满足条件的子串可能有很多,但是题目保证满足条件的最短的子串唯一。
找出的最短子串为.
注意:
如果 s 中没有包含 t 中所有字符的子串,返回空字符串 “”;
满足条件的子串可能有很多,但是题目保证满足条件的最短的子串唯一。
"XDOYEZODEYXNZ","XYZ"
"YXNZ"
"abcAbA","AA"
"AbA"
class Solution: def minWindow(self , S: str, T: str) -> str: # write code here dict_ = {} min_len = 10001 n = len(S) for i in T: dict_[i] = T.count(i) l, r = 0, 0 counter = len(T) ans_l, ans_r = 0, 0 while r<n: if S[r] in dict_ and dict_[S[r]]>0: counter-=1 if S[r] in dict_: dict_[S[r]]-=1 if counter==0: while l<n: if S[l] in dict_ and dict_[S[l]]<0: dict_[S[l]]+=1 elif S[l] in dict_ and dict_[S[l]]==0: if r-l+1<min_len: min_len = r-l+1 ans_l, ans_r = l, r+1 counter+=1 dict_[S[l]]+=1 l+=1 break l+=1 r+=1 return S[ans_l:ans_r]
class Solution: def minWindow(self , S: str, T: str) -> str: # write code here if len(S)==0&nbs***bsp;len(T)==0&nbs***bsp;len(S) < len(T): return "" # 准备两本字典,分别记录T的词频和S子串的词频 freqT = {} freqS = {} for string in T: if string not in freqT.keys(): freqT[string] = 1 else: freqT[string] += 1 q = [] # 准备队列一个,依次记录在S中发现的T字符索引 cnt = 0 # 计数器, 记录T中字符是否被查全 length = len(S) + 1 j = 0 tail = 0 head = 0 while j < len(S): if S[j] in freqT.keys(): # 统计S中子串词频 if S[j] not in freqS.keys(): freqS[S[j]] = 1 else: freqS[S[j]] += 1 # 当S的某个单词词频《=T时,表明单词没有查全,计数器加 1, if freqS[S[j]] <= freqT[S[j]]: cnt += 1 # 字符索引入队 q.append(j) # 当单词查全时, 记录长度,同时队头出队,出队单词词频减 1 while cnt >= len(T): if q[-1] - q[0] + 1 < length: head = q[0] tail = q[-1] length = tail - head + 1 s = q.pop(0) freqS[S[s]] -= 1 if freqS[S[s]] < freqT[S[s]]: cnt -= 1 j += 1 if length == len(S) + 1: return "" else: return S[head:tail+1]
哈希表 + 双指针的滑动窗口,找到包含T的所有字符,缩小窗口找到最小子串
时间复杂度:O(len(T)*len(S)+len(T)) 空间复杂度:O(len(T))
class Solution: def check(self, mp): for key, value in mp.items(): if value < 0: return False return True def minWindow(self , S: str, T: str) -> str: mp = {} low = 0 high = 0 left = -1 right = -1 len_ = len(S) + 1 for i in T: if i in mp: mp[i] -= 1 else: mp[i] = -1 for j in range(len(S)): if S[high] in mp: mp[S[high]] += 1 while self.check(mp): if len_ > high - low + 1: len_ = high - low + 1 left = low right = high if S[low] in mp: mp[S[low]] -= 1 low += 1 high += 1 if left == -1: return '' return S[left:right+1]
class Solution: def minWindow(self , S: str, T: str) -> str: # write code here n = len(S) m = len(T) if (n == 0&nbs***bsp;m == 0): return '' # 使用双指针,表示用来匹配T的S子串的左右索引 index_1 = 0 index_2 = -1 # min为最短长度子串的左索引, min_len为最短长度 min = 0 min_len = n+1 # pattern用字典来记录T中所有字符的出现次数 # d用来记录双指针中间子串包含pattern中字符的次数 # lack表示子串要包含T还缺少哪些字符,缺多少个 d = {} pattern = {} lack = {} # 把lack和pattern初始化为T中各个字符的出现次数 # d初始化为0次 for i in T: if i not in d: lack[i] = 1 pattern[i] = 1 d[i] = 0 else: lack[i] += 1 pattern[i] += 1 # 如果右指针超过了S的长度,结束循环 while (index_2 < n): # lack为空也就是S的子串还没有包含所有T if (lack != {}): # 考虑右指针右移的新增字符 index_2 = index_2 + 1 if (index_2 >= n): break # 如果新增字符在T中 if (S[index_2] in pattern): # 则d中对应字符的次数加1,lack中对应的减1, # 如果lack中值为0,则表明不再缺了,删除键值 d[S[index_2]] += 1 if (S[index_2] in lack): lack[S[index_2]] -= 1 if (lack[S[index_2]] == 0): lack.pop(S[index_2]) # 如果lack为空,也就是子串已经包含T # 左指针右移,逐渐缩小区间 else: if (index_2 - index_1 + 1 < min_len): min_len = index_2 - index_1 + 1 min = index_1 # 如果删掉的字符在pattern中,则d的对应次数减1 # 如果d中的出现次数少于pattern中的出现次数 # 说明子串中该字符比T的要少了,缺少这个字符 if (S[index_1] in pattern): d[S[index_1]] -= 1 if (d[S[index_1]] < pattern[S[index_1]]): lack[S[index_1]] = 1 index_1 += 1 if (min_len == n+1): return '' return (S[min: min+min_len])