滑动窗口,哈希表系列问题
********************************
如有侵权,我会删除。
滑动窗口,哈希表问题模板
window={}
left,right =0, 0
while right <len(s):
#增大窗口
window[s[right]]
right += 1
while window needs shrink:
#缩小窗口
window[s[left]] -= 1
left += 1
一、最长不含重复字符的子字符串
def lengthOfLongestSubstring(self , s: str) -> int:
# write code here
#window = {}这样直接用会报错
from collections import defaultdict
window = defaultdict(int)
left,right = 0,0
res = 0
# 先移动right,将s字符装进window
while right<len(s):
c = s[right]
right += 1
window[c] += 1
#发现当前字符哈希表中已经存在了
while window[c]>1:
#收缩左侧窗口
d = s[left]
left += 1
window[d] -= 1
res = max(res,right-left)
return res
二、最小覆盖子串
def minWindow(self, s: str, t: str) -> str:
from collections import defaultdict
window = defaultdict(int)#存储窗口里t字符串中各字符出现的个数
target = defaultdict(int) #存储t字符串中各个字符出现的个数
valid = 0 #窗口中满足taret条件的字符数
start,cur_len=0,float('inf')#存储当前最小覆盖子串的起始索引和长度
left,right = 0,0 #滑动窗口的左右边界
for c in t:
target[c]+=1 #t字符串中各个字符出现的个数
while(right<len(s)): # right不超过s串范围的条件下滑动窗口
c = s[right] #随着right右移,即将被加入窗口的字符
right += 1#右移right指针
if(c in target):#如果待加入窗口的字符在target中
window[c] += 1#c计入window
if(window[c] == target[c]):#如果字符进入窗口后,窗口内这个字符的个数和target中这个字符个数一样,就将valid计数加1
valid += 1
while(valid == len(target)):#当前窗口里的子串是可行解
#更新当前最优值
if(right-left<cur_len):#找到更短的覆盖子串
start = left
cur_len = right-left
d = s[left] #即将被移出窗口的字符
left += 1#右移left指针
if(d in target): #如果待移出窗口的字符在target中
if(window[d] == target[d]): #如果此时字符d在窗口中出现的次数和在target中出现的次数一样,那么移出d后,valid就要减1。
valid -= 1
window[d] -= 1 #更新窗口内字符计数
return "" if cur_len == float('inf') else s[start:start+cur_len]
三、字符串排列
相当于判断s中是否存在一个字串,只包含T中所有字符。
class Solution:
def checkInclusion(self, t: str, s: str) -> bool:
from collections import defaultdict
window,need= defaultdict(int), defaultdict(int)
for c in t:
need[c] += 1
#return need
left,right = 0, 0
valid = 0
while right <len(s):
c=s[right]
right += 1
if c in need:
window[c] += 1
if window[c] == need[c]:
valid += 1
while right-left >=len(t):
#return len(need)
#判断是否找到了合法子串
if valid == len(need):
return True
d=s[left]
left += 1
if d in need:
if window[d] == need[d]:
valid -= 1
window[d] -= 1
return False
四、找所有字母异位词
相当于找到s中所有t的排列,并返回起始索引。
class Solution:
def findAnagrams(self, s: str, t: str) -> List[int]:
from collections import defaultdict
window ,need= defaultdict(int), defaultdict(int)
for c in t:
need[c] += 1
#return need
left,right = 0, 0
valid = 0
res = []
while right <len(s):
c=s[right]
right += 1
if c in need:
window[c] += 1
if window[c] == need[c]:
valid += 1
while right-left >=len(t):
#当窗口符合条件时,把起始索引加入到res
if valid == len(need):
res.append(left)
d=s[left]
left += 1
#原来用的if need[d]:,结果输出[0]
#if need[d]:
if d in need:
if window[d] == need[d]:
valid -= 1
window[d] -= 1
return res