给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例 1:
输入:s = “ADOBECODEBANC”, t = “ABC”
输出:“BANC”
示例 2:
输入:s = “a”, t = “a”
输出:“a”
提示:
1 <= s.length, t.length <= 105
s 和 t 由英文字母组成
此题是明显的滑动窗口解法,暴力的解法时间复杂度过高,在生产环境中往往不能让人满意。
class Solution {
public:
string minWindow(string s, string t) {
//初始化窗口和子串
unordered_map<char,int> need,Window;
//将子串如表
for(char c:t) need[c]++;
//窗口边界标定
int left=0,right = 0;
//有效字符统计
int valid = 0;
//开始的位置和长度记录
int start= 0, len = INT_MAX;//2^31 -1;
//开始进行窗口滑动
while(right<s.size())
{
//字符进行窗口
char c = s[right];
//移动窗口右边界
right++;
//进行窗口内数据的更新。检查进入窗口的是不是需要的字符。是才进行更新,不是的话不进行任何更新
if(need.count(c))
{
//元素加入窗口
Window[c]++;
//判定匹配个数。
if(Window[c]==need[c])
valid++;//匹配上有效个数加一
}
//当有效的窗口生成后,即窗口完全包含子串。进行更新左侧窗口
while(valid == need.size())
{
//更新最小覆盖子串长度。即现有窗口长度
if(right - left <len)
{
//窗口开始位置
start = left;
//窗口大小
len = right-left;
}
//移出窗口字符
char d = s[left];
//窗口收缩左边界
left++;
//查看字符是否在子串中
if(need.count(d))
{
//在子串中且和窗口匹配
if(Window[d]==need[d])
{
//匹配字符减一
valid--;
}
//窗口中的有效字符去除
Window[d]--;
}
}
}
return len == INT_MAX ? "":s.substr(start,len);
}
};