Problem Statement
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
Note
- 对于
t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
- 如果
s 中存在这样的子串,我们保证它是唯一的答案。
Sample #1
1
2
3
|
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
|
Sample #2
1
2
3
|
输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。
|
Sample #3
1
2
3
4
|
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
|
Constraints
m == s.length
n == t.length
1 <= m, n <= 105
s 和 t 由英文字母组成
Solving
滑动窗口典型例题,我们维护一个CNT欠款数组,每当右边界遍历到新的字符时实现CNT[s[r]]++,当且仅当此字符CNT<0即属于t串所欠字符时算为有效还款。不断滑动窗口找出所有欠款还清时的左边界和此时的窗口长度,利用substr返回字串即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
class Solution {
public:
string minWindow(string s, string t) {
if(s.size()<t.size()) return "";
int tl = t.size();
int cnt[267] = {0};
int debt = tl;
int ans = INT_MAX;
for(int i=0;i<tl;i++)
{
cnt[(int)t[i]]--;
}
int start = 0;
string ansstr = "";
for(int l=0,r=0;r<s.size();r++)
{
if(cnt[s[r]]<0)
{
debt--;
}
cnt[s[r]]++;
if(debt==0)
{
while(cnt[s[l]]>0)
{
cnt[s[l++]]--;
}
if(r-l+1<ans)
{
ans = r-l+1;
start = l;
}
}
}
return ans==INT_MAX?"":s.substr(start,ans);
}
};
|