题目链接 : https://leetcode-cn.com/problems/minimum-window-substring/
题目描述:
给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。
示例:
输入: S = "ADOBECODEBANC", T = "ABC"
输出: "BANC"
思路:
滑动窗口
我们只要保证窗口(队列)字符串含有t
中字符的个数大于等于t
里相应元素个数.如方法一
还有一种方法记录队列元素和t
中元素的差异,直接看代码,很好理解!
代码:
lass Solution:
def minWindow(self, s: 'str', t: 'str') -> 'str':
from collections import Counter
t = Counter(t)
lookup = Counter()
start = 0
end = 0
min_len = float("inf")
res = ""
while end < len(s):
lookup[s[end]] += 1
end += 1
#print(start, end)
while all(map(lambda x: lookup[x] >= t[x], t.keys())):
if end - start < min_len:
res = s[start:end]
min_len = end - start
lookup[s[start]] -= 1
start += 1
return res
另一种方法
python
class Solution:
def minWindow(self, s: 'str', t: 'str') -> 'str':
from collections import defaultdict
lookup = defaultdict(int)
for c in t:
lookup[c] += 1
start = 0
end = 0
min_len = float("inf")
counter = len(t)
res = ""
while end < len(s):
if lookup[s[end]] > 0:
counter -= 1
lookup[s[end]] -= 1
end += 1
while counter == 0:
if min_len > end - start:
min_len = end - start
res = s[start:end]
if lookup[s[start]] == 0:
counter += 1
lookup[s[start]] += 1
start += 1
return res
java
class Solution {
public String minWindow(String s, String t) {
Map<Character, Integer> lookup = new HashMap<>();
for (char c : s.toCharArray()) lookup.put(c, 0);
for (char c : t.toCharArray()) {
if (lookup.containsKey(c)) lookup.put(c, lookup.get(c) + 1);
else return "";
}
int start = 0;
int end = 0;
int min_len = Integer.MAX_VALUE;
int counter = t.length();
String res = "";
while (end < s.length()) {
char c1 = s.charAt(end);
if (lookup.get(c1) > 0) counter--;
lookup.put(c1, lookup.get(c1) - 1);
end++;
while (counter == 0) {
if (min_len > end - start) {
min_len = end - start;
res = s.substring(start, end);
}
char c2 = s.charAt(start);
if (lookup.get(c2) == 0) counter++;
lookup.put(c2, lookup.get(c2) + 1);
start++;
}
}
return res;
}
}
下面介绍关于滑动窗口的万能模板,可以解决相关问题,相信一定可以对滑动窗口有一定了解!
还有类似题目有:
3. 无重复字符的最长子串
class Solution:
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
from collections import defaultdict
lookup = defaultdict(int)
start = 0
end = 0
max_len = 0
counter = 0
while end < len(s):
if lookup[s[end]] > 0:
counter += 1
lookup[s[end]] += 1
end += 1
while counter > 0:
if lookup[s[start]] > 1:
counter -= 1
lookup[s[start]] -= 1
start += 1
max_len = max(max_len, end - start)
return max_len
76. 最小覆盖子串
class Solution:
def minWindow(self, s: 'str', t: 'str') -> 'str':
from collections import defaultdict
lookup = defaultdict(int)
for c in t:
lookup[c] += 1
start = 0
end = 0
min_len = float("inf")
counter = len(t)
res = ""
while end < len(s):
if lookup[s[end]] > 0:
counter -= 1
lookup[s[end]] -= 1
end += 1
while counter == 0:
if min_len > end - start:
min_len = end - start
res = s[start:end]
if lookup[s[start]] == 0:
counter += 1
lookup[s[start]] += 1
start += 1
return res
159. 至多包含两个不同字符的最长子串
class Solution:
def lengthOfLongestSubstringTwoDistinct(self, s: str) -> int:
from collections import defaultdict
lookup = defaultdict(int)
start = 0
end = 0
max_len = 0
counter = 0
while end < len(s):
if lookup[s[end]] == 0:
counter += 1
lookup[s[end]] += 1
end +=1
while counter > 2:
if lookup[s[start]] == 1:
counter -= 1
lookup[s[start]] -= 1
start += 1
max_len = max(max_len, end - start)
return max_len
340. 至多包含 K 个不同字符的最长子串
class Solution:
def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int:
from collections import defaultdict
lookup = defaultdict(int)
start = 0
end = 0
max_len = 0
counter = 0
while end < len(s):
if lookup[s[end]] == 0:
counter += 1
lookup[s[end]] += 1
end += 1
while counter > k:
if lookup[s[start]] == 1:
counter -= 1
lookup[s[start]] -= 1
start += 1
max_len = max(max_len, end - start)
return max_len
滑动窗口题目:
3. 无重复字符的最长子串
30. 串联所有单词的子串
76. 最小覆盖子串
159. 至多包含两个不同字符的最长子串
209. 长度最小的子数组
239. 滑动窗口最大值
567. 字符串的排列
632. 最小区间
727. 最小窗口子序列
同步更新博客:
一起刷LeetCode - 威行天下 - 博客园www.cnblogs.com