题目
题目链接
两个字符串:S,T
,要求找出S
中【包含T
中所有字母(顺序可以不一致)】的最短子串
思路
双指针+哈希表
-
使用2个指针
i,j
,初始时均指向0,S[i:j+1]
为当前正在处理的子串 -
使用一个字典
needDict
作为哈希表,存放T
中所有字母以及出现次数
如T='ZXYZ'
则needDict={‘Z’:2,'Y':1,'X':1}
在遍历S
取子串S[i:j+1]
的过程中,needDict
中键对应的值可能会变成以下情况:
>0表示子串中还缺少这个字母
=0表示子串中这个字母数量正好足够
<0表示子串中这个字母数量比T中的多
matched
记录当前已经匹配的字母数,当matched
=T的长度
时,说明当前子串S[i:j+1]
满足题目需要minLen
,dst
分别记录符合要求的最短子串长度和最短子串,minLen
初始为无穷大,dst
初始为空串
遍历S
取子串:j
每次+1,到S
末尾停止
-
若
S[j]
在needDict
中, 将needDict
中键S[j]
对应的值-1
若此时needDict[S[j]]
还>=0
,说明本次匹配到一个还缺少的字母,令matched
+1 -
若matched=T的长度,说明当前字符串满足了题目需要,可以让
i
不断右移缩短子串长度,同时维护needDict[S[i]]
的值,直到子串S[i:j+1]
不再满足要求:
若S[i]
在needDict
中,把needDict[S[i]]
-1,如果这个操作使得needDict[S[i]]
>0,说明i
右移移走S[i]
这个字母会使得S[i:j+1]
不再满足题目需要,此时更新最短的子串,并令matched
-1
代码
class Solution:
def minWindow(self, S, T):
# 空串,或者S比T还短
if not S or not T or len(S)<len(T):
return ''
i,j=0,0
minLen=float('inf')
dst=''
matched=0
needDict={}
# 根据T初始化哈希表
for char in T:
needDict[char]=needDict.get(char,0)+1
# 对S取子串
for j in range(len(S)):
# 当前字母是T中的字母(①可能子串中还缺少这个字母,②也可能数量已经够了,但都要令键对应的值-1)
if S[j] in needDict:
needDict[S[j]] -= 1
# 如果是前一种情况,让matched+1表示匹配了一个尚需要的字母
if needDict[S[j]]>=0:
matched+=1
# 当前子串满足需要,更新最短子串
# 并让i右移直到当前子串不再符合需要
while matched==len(T):
if S[i] in needDict:
if j+1-i<minLen:
dst=S[i:j+1]
minLen=j+1-i
needDict[S[i]]+=1
if needDict[S[i]]>0:
matched-=1
i+=1
return dst