思路
滑动窗口双指针
变量:
left, right为当前窗口的开始和结尾索引
dict_s, dict_p分别为待匹配字符串和模式串相关的字典,他们的key是模式串的各个字符,value为各个字符在字符串中出现的次数
valid为当前窗口待匹配串和模式串已经匹配上的字符的种数,不是个数
start为当前的最短的覆盖子串的起始索引
min_len为当前的最短的覆盖子串的长度
string为待匹配串
pat为模式串
前置工作:
遍历pat串,填充dict_p。具体是,统计pat中各个字符出现的次数,用dict_p保存。
过程:
1,left,right都从0开始,滑动对象是string
2,right往右滑动,令当前字符为c,如果c在dict_p中,dict_s[c] += 1。如果dict_p[c]==dict_s[c], valid+=1
3,如果valid等于len(dict_p),说明当下窗口有符合的覆盖子串。如果当前窗口长度小于min_len,则令start=left, len_min为当前窗口长度。left向右滑动,令pass_c为string[left-1],如果pass_c在dict_p中,那么dict_s[pass_c]-=1,如果dict_s[pass_c]<dict_p[pass_c],valid-=1。重复这个过程,直到valid不等于len(dict_p),再回到步骤2。
时间复杂度O(n)
空间复杂度O(n)
链接
代码
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param S string字符串
# @param T string字符串
# @return string字符串
#
class Solution:
def minWindow(self , S: str, T: str) -> str:
# write code here
string, pat = S, T
dict_s = {}
dict_p = {}
for c in pat:
if c not in dict_p:
dict_p[c] = 1
else:
dict_p[c] += 1
len_p = len(pat)
valid = 0
left = 0
start = 0
min_len = float("inf")
for right in range(len(string)):
c = string[right]
if c in dict_p:
# print(c)
if c not in dict_s:
dict_s[c] = 1
else:
dict_s[c] += 1
if dict_s[c] == dict_p[c]:
valid += 1
# print(valid, len_p)
while valid == len(dict_p):
cur_len = right-left+1
if cur_len < min_len:
min_len = cur_len
start = left
left += 1
pass_c = string[left-1]
if pass_c in dict_p:
dict_s[pass_c] -= 1
if dict_s[pass_c] < dict_p[pass_c]:
valid -= 1
if min_len == float("inf"):
return ""
return string[start:start+min_len]