76. 最小覆盖子串
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
示例 2:
输入:s = "a", t = "a"
输出:"a"
提示:
1 <= s.length, t.length <= 10^5
s 和 t 由英文字母组成
-
解题思路(双指针维护一个滑动窗口)
-
先统计
t字符串中的字符及个数; -
设置
cnt为t的长度,是一共需要匹配的字符个数; -
扩大窗口,并判断当前字符是否可以匹配的上,如果匹配的上,则
cnt--; -
若
cnt == 0说明已经完全匹配,此时需要扩大左边界,如果左边界的字符移出窗口导致不能够完全匹配(S[s[l]] < T[s[l]]),cnt++,当cnt > 0,此时判断是否需要更新答案。
-
| C++版本 |
class Solution {
public:
string minWindow(string s, string t) {
int S[256] = {0},T[256] = {0};
for(auto x : t) T[x]++;
int n = s.size(),cnt = t.size(); //cnt是待匹配的字符的个数
int len = n + 1,idx = -1; //idx是最小覆盖子串的起始下标,len是子串的长度
for(int l = 0, r = 0; r < n; r++){
S[s[r]]++;
if(S[s[r]] <= T[s[r]]) //匹配上一个待匹配的字符
cnt--;
while(l <= r && cnt == 0){ //cnt == 0说明已经完全匹配成功
S[s[l]]--;
if(S[s[l]] < T[s[l]]) cnt++;
if(cnt > 0) //如果cnt == 0 变成了小于0 则说明当前l-r的区间是完全匹配的,此时更新答案
if(len > r - l + 1) {
len = r - l + 1;
idx = l;
}
l++; //缩短区间
}
}
return idx == -1 ? "" : s.substr(idx,len);
}
};
| Python版本 |
class Solution:
def minWindow(self, s: str, t: str) -> str:
S = collections.Counter(t)
cnt = len(t)
n = len(s)
dic,l,r,res,Len = {},0,0,"", n + 1
while r < n:
if s[r] not in dic:
dic[s[r]] = 1
else:
dic[s[r]] += 1
if(dic[s[r]] <= S[s[r]]):
cnt -= 1
while l <= r and cnt == 0: #完全匹配,收缩窗口
dic[s[l]] -= 1
if dic[s[l]] < S[s[l]]:
cnt += 1
if cnt > 0:
if Len > r - l + 1:
res = s[l:r + 1]
Len = r - l + 1
l += 1
r += 1
return res

895

被折叠的 条评论
为什么被折叠?



