hard做的人想吐,暴力超时,要用滑动窗口和map,最重要的操作是弹出左边那些不要的元素,这样更新的left再去和minLen比。然后left再++,因为left++了,所以肯定不满足了,让right也++,直到right走到最后一位
class Solution {
public:
string minWindow(string s, string t) {
if(t.length() == 0) return s.substr(0,1);
if(t.length() > s.length()) return "";
//window肯定是滑动窗口
//int left = -1, minLen = INT_MAX;
//不用数组记录每一位往后数几位才是最大值,直接记录最小长度的下标和长度即可
//还得来一个map记录当前字符串中还没被消耗的个数
/*for(int i = 0; i <= s.length()-t.length(); ++i){
unordered_map<char,int> ma;
for(int j = 0; j < t.length(); ++j){
ma[t[j]]++;
}
//来一个index判断被消耗掉几个
int index = t.length();
for(int j = i; j < s.length(); ++j){
if(ma[s[j]] != 0){
ma[s[j]]--;
index--;
}
if(index == 0 && minLen > j-i+1){
left = i;
minLen = j-i+1;
}
}
}*/
//暴力超时用滑动窗口
unordered_map<char,int> ma;
for(char c:t){
ma[c]++;
}
//index是t中没被消耗掉的字符个数
int left = 0, right = 0,minLen = INT_MAX, index = t.length(), start = 0;
while(right < s.length()){
//当index==0时,证明一个窗口找好了,但是不一定是最小窗口,将left一直右移,将前面那些没用的字符全部不要,直到找到第一个需要的字符,也就是ma[s[left]]刚好为0的字符,此时这个窗口是最小的,更新minLen和start,并将left++
//left++后,一定不满足了,所以r++重新找新的窗口。
if(ma[s[right]] > 0){
index--;
}
ma[s[right]]--;
if(index == 0){
while(left < right && ma[s[left]]<0){
//把前面没有那些字符都去除
ma[s[left++]]++;
}
if(right-left+1 < minLen){
start = left;
minLen = right-left+1;
}
ma[s[left]]++;
index++;
left++;
}
right++;
}
if(minLen == INT_MAX) return "";
else return s.substr(start,minLen);
}
};