Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
Example:
Input: S = "ADOBECODEBANC", T = "ABC"
Output: "BANC"
Note:
- If there is no such window in S that covers all characters in T, return the empty string
""
. - If there is such window, you are guaranteed that there will always be only one unique minimum window in S.
LeetCode:链接
基础:LeetCode3:Longest Substring Without Repeating Characters
双指针 + hash table。
双指针思想,尾指针不断往后扫,当扫到有一个窗口包含了所有T的字符,然后再收缩头指针,直到不能再收缩为止。最后记录所有可能的情况中窗口最小的。
使用right指针向右搜索,同时要记录在left~right这个区间内包含的T中每个元素出现的个数和。如果在[left,right]区间内,元素出现的个数和与T长度相等了,说明在这个区间是符合要求的一个区间,但是不一定是最短区间。
因此,现在要移动left指针,要求,在[left, right]区间内的元素出现个数应该把T中所有的元素都包含。同样使用cnt来验证是否包含了T所有的元素。在移动left指针的时候要注意存储最短的子串,当所有的循环都结束之后最短字符串即为题目要求了。这个题难点就在于维护cnt。
class Solution(object):
def minWindow(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
s_dict, t_dict = {}, {}
start, end = 0, 0
min_length = float('inf')
cnt = 0
res = ""
for c in t:
t_dict[c] = t_dict.get(c, 0) + 1
for c in s:
s_dict[c] = s_dict.get(c, 0) + 1
# 统计窗口中有t字典的字符个数,不大于t的字典次数才算数
if c in t_dict and s_dict[c] <= t_dict[c]:
cnt += 1
# 收缩start指针
while cnt == len(t) and start <= end:
print(start, end)
if min_length > end - start + 1:
min_length = end - start + 1
res = s[start:end+1]
s_dict[s[start]] -= 1
# 因为s的字典已经减1了 所以判断条件必须小于才能将cnt减1
if s[start] in t_dict and s_dict[s[start]] < t_dict[s[start]]:
cnt -= 1
start += 1
end += 1
return res