**76. Minimum Window Substring 最小覆盖子串
1. 原始题目
给定一个字符串 S 和一个字符串 T,请在 S 中找出包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC" 输出: "BANC"
说明:
- 如果 S 中不存这样的子串,则返回空字符串
""。 - 如果 S 中存在这样的子串,我们保证它是唯一的答案。
2. 思路
双指针滑动窗口。[i,j]左闭又闭区间表示当前子串。如果当前子串包好含了所有目标字符,则记录当前结果,i右移,并判断右移时是否有目标字符被移出去。否则j继续向右扩展。
3. 实现
1 class Solution:
2 def minWindow(self, s: str, t: str) -> str:
3 if not s: return ''
4 c = Counter(t) # 目标串的计数器字典
5 temp = defaultdict(int) # 当前子串的字典
6 i,j = 0,-1 # i,j为左闭又闭区间,表示当前字符串
7 len_temp = 0 # 记录当前子串完整包含目标串元素的个数
8 res=s+'!' # 初始化结果字符串
9 while(i<len(s)):
10 if j+1<len(s) and len_temp<len(c): # 如果当前串没有完整包含目标串
11 temp[s[j+1]]+=1 # 将下一个元素纳入
12 if temp[s[j+1]] == c[s[j+1]]: # 如果此时该元素满足了目标串数目的要求,则子串长度加1
13 len_temp+=1
14 j+=1 # 有边界右移
15 elif len_temp==len(c): # 如果当前串完整包含了目标串
16 res = res if len(res)<len(s[i:j+1]) else s[i:j+1] # 先看看是否有更好的解
17 if s[i] in c and temp[s[i]]<=c[s[i]]: # 该右移左边界了,看看是否破环了串完整度
18 len_temp-=1 # 如果把重要的字符移出去了,长度应该减1
19 temp[s[i]]-=1 # 计数相应-1
20 i+=1 # 左边界右移
21 else:
22 break # 都不满足条件则应该break
23
24 return '' if res==s+s else res
leetcode解题区也有完整python实现:
1 def minWindow(self, s, t):
2 """
3 :type s: str
4 :type t: str
5 :rtype: str
6 """
7
8 if not t or not s:
9 return ""
10
11 # Dictionary which keeps a count of all the unique characters in t.
12 dict_t = Counter(t)
13
14 # Number of unique characters in t, which need to be present in the desired window.
15 required = len(dict_t)
16
17 # left and right pointer
18 l, r = 0, 0
19
20 # formed is used to keep track of how many unique characters in t are present in the current window in its desired frequency.
21 # e.g. if t is "AABC" then the window must have two A's, one B and one C. Thus formed would be = 3 when all these conditions are met.
22 formed = 0
23
24 # Dictionary which keeps a count of all the unique characters in the current window.
25 window_counts = {}
26
27 # ans tuple of the form (window length, left, right)
28 ans = float("inf"), None, None
29
30 while r < len(s):
31
32 # Add one character from the right to the window
33 character = s[r]
34 window_counts[character] = window_counts.get(character, 0) + 1
35
36 # If the frequency of the current character added equals to the desired count in t then increment the formed count by 1.
37 if character in dict_t and window_counts[character] == dict_t[character]:
38 formed += 1
39
40 # Try and contract the window till the point where it ceases to be 'desirable'.
41 while l <= r and formed == required:
42 character = s[l]
43
44 # Save the smallest window until now.
45 if r - l + 1 < ans[0]:
46 ans = (r - l + 1, l, r)
47
48 # The character at the position pointed by the `left` pointer is no longer a part of the window.
49 window_counts[character] -= 1
50 if character in dict_t and window_counts[character] < dict_t[character]:
51 formed -= 1
52
53 # Move the left pointer ahead, this would help to look for a new window.
54 l += 1
55
56 # Keep expanding the window once we are done contracting.
57 r += 1
58 return "" if ans[0] == float("inf") else s[ans[1] : ans[2] + 1]

浙公网安备 33010602011771号