每日一题:
难度:困难
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
/*
如何判断当前的窗口包含所有 tt 所需的字符呢?我们可以用一个哈希表表示 tt 中所有的字符以及它们的个数,用一个哈希表动态维护窗口中所有的字符以及它们的个数,如果这个动态表中包含 tt 的哈希表中的所有字符,并且对应的个数都不小于 tt 的哈希表中各个字符的个数,那么当前的窗口是「可行」的。
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/minimum-window-substring/solution/zui-xiao-fu-gai-zi-chuan-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
class Solution {
public:
unordered_map<char,int> mapt, maps;
//mapt存储t, maps存储s中包含t的字符
bool check(){ //判断是否s中L-R的字符是否完全包含t
for(const auto &it : mapt){ //循环遍历mapt中的数
if(maps[it.first] < it.second) return false;
}
return true;
}
string minWindow(string s, string t) {
for(const auto &i : t){
mapt[i]++;
}
int L = 0, ansL = -1, R = -1, len = INT_MAX;
/*
L: 用于移动左边的窗口
R: 用于移动右边的窗口
ansL:用于获取返回界限的左边极限
len: 用于返回值的长度记录
*/
while(R < int(s.size())) //循环遍历s字符串
{
// cout<<"0";
if(mapt.find(s[++R]) != mapt.end()){ //只把存在于t中的字符用mapt保存下来
maps[s[R]]++;
}
while(check() && L <= R){ //check通过表示s中含有全部的t
if(len > R - L +1){
len = R - L + 1;
ansL = L;
// std::cout << "1" ;
}
//当窗口满足时,不断地缩短左边的极限
if(mapt.find(s[L]) != mapt.end()){
mapt[s[L]]--;
}
L++;
}
}
//ansL == -1?如果相等,则返回空的字符串
std::cout<<len;
return ansL == -1? string() : s.substr(ansL, len);
}
};