思路:
使用一个滑动窗口来表示s子串。
用一个hash表来表示s子串还需要哪些字母才能包含t的全部字母
另外再用一个count来计数,count等于t的长度,那么该子串就是一个符合条件的子串。
再将左指针向右移动。
string minWindow(string s, string t) {
//如果s比t短,直接返回空字符串
if(s.size()<t.size())
return "";
//hashmap存储还需要多少字符才能达到要求
//注意:hashmap的值是可以为负数的,比如hashmap[c]=-1就表示该子串所包含的c比要求的还多一个
//还有,hashmap中的元素项都是t字符串的字符,
//如果不是t字符串中的字符,我们根本就不处理,右边界直接右移
map<char,int> hashmap;
for(auto c:t)
hashmap[c]= hashmap.find(c)!=hashmap.end() ? hashmap[c]+1 : 1;
//用来计数,所包含的符合要求的字符有多少
int count=0;
//目前子串的左右边界指针
int left=0;
int right=0;
//最短长度,以及左右边界
int minleft=0;
int minright=0;
int minlen=INT_MAX;
//窗口向右扩展
for(;right<s.size();++right){
//如果s[right]是t中的字符
if(hashmap.find(s[right]) != hashmap.end()){
//如果我们还需要s[right],那么将其纳入窗口后,所包含的符合要求的字符就又多了一个
if(hashmap[s[right]]>0)
++count;
//所需要的字符也减少了一个
--hashmap[s[right]];
}
//此时我们得到了所需要的子串
while(count == t.size()){
//如果该子串更短,则更新记录
if(right-left<minlen){
minright=right;
minleft=left;
minlen=right-left;
}
//如果s[left]是t中的字符
if(hashmap.find(s[left]) != hashmap.end()){
//如果s[left]是我们还需要的或者刚刚够的,那么所包含的符合要求的字符就减少一个
//如果此时hashmap[s[left]]<0,就说明子串所包含的字符还有多的,不需要减少
if(hashmap[s[left]]>=0)
--count;
//所需要的字符增加一个
++hashmap[s[left]];
}
//左边界右移
++left;
}
}
//最后如果存在符合条件的子串,则构建该子串
return minlen == INT_MAX ? "" : string(s.begin()+minleft,s.begin()+minright+1);
}