给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。
注意:
- 对于
t中重复字符,我们寻找的子字符串中该字符数量必须不少于t中该字符数量。 - 如果
s中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"输出:"BANC"
示例 2:
输入:s = "a", t = "a"
输出:"a"
示例 3:
输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。
提示:
1 <= s.length, t.length <= 105s和t由英文字母组成
进阶:你能设计一个在 o(n) 时间内解决此问题的算法吗?
class Solution {
public:
string minWindow(string s, string t) {
vector<int> need(128,0); //ASCII码范围是0-127
int count = t.length(); //统计还有没找到的字符串的个数
for(char c : t)
{
need[c]++;
}
int l=0, r=0, start=0, size = INT_MAX;
while(r<s.length())
{
char c = s[r];
if(need[c]>0) count--; //先判断是否大于0
need[c]--; //位置不能前,先把右边的字符加入窗口 ,小于0说明不在t内,区分开
if(count==0) //窗口中已经包含所需的全部字符
{
while(l<r && need[s[l]]<0) //缩减窗口,出这个while时l加到了存在的t上
{
need[s[l]]++;
l++;
} //此时窗口符合要求
if(r-l+1 < size) //更新答案
{
size = r-l+1;
start = l; //更新最后用来取子字符串的起点
}
need[s[l]]++; //左边界右移之前需要释放need[s[l]],后面要用到
l++;
count++;
}
r++;
}
return size==INT_MAX ? "" : s.substr(start, size);
}
};
