1.问题描述:s的子串覆盖t的所有元素,不要求顺序。只看s子串中玩不完全包含t的所有元素。
a,双指针同时指向s的头,后指针先往后移,前指针不动,一直移到了刚好包含t。(这是一个子串,记录大小找下一个)
b,此时移动前指针移到刚好不包含t,继续移动后指针,再到刚好包含t,此时这个窗口大小是上面这个尾部时的最小窗口。
c,重复ab过程直至最后一次移动后指针时大于s的长度。
3.简述为什么这样可以找到,这是遍历法的改进,遍历法就是找出所有长度大于s的子集,看看谁最小,滑动窗口简化了,
因为a过程刚好包含了t之后,后面再有也不会比这个集合小了。b过程就是找以刚刚这个刚好包含的这个可行解的最优解。eg:t:xy s:zzxy y或zxy y
4.怎么知道刚好包含,哈希表,键是t的每个元素,键值是键的频数。
初始化键值都是-1(重复2的就是-2),在后指针移动的过程中,遇到对应的键,键值就+1,
classSolution {
public:
//检查是否有小于0的
bool check(unordered_map<char, int> &hash) {
for(auto iter = hash.begin(); iter != hash.end(); iter++) {
if(iter->second < 0)
returnfalse;
}
returntrue;
}
string minWindow(string S, string T) {
int cnt = S.length() + 1;
//记录目标字符串T的字符个数
unordered_map<char, int> hash;
for(int i = 0; i < T.length(); i++)
//初始化哈希表都为负数,找的时候再加为正
hash[T[i]] -= 1; //是频数-=
int slow = 0, fast = 0;
//记录找到的局部最优解左右区间
int left = -1, right = -1;
for(; fast < S.length(); fast++){
char c = S[fast];
//目标字符匹配+1
if(hash.count(c))
hash[c]++;
//没有小于0的说明都覆盖了,缩小窗口,即可以移动前指针了
while(check(hash)){
//取最优解
if(cnt > fast - slow + 1){
cnt = fast - slow + 1; //cnt记录以当前后指针所在位置为结尾的最优解的长度
left = slow;
right = fast;
}
char c = S[slow];
if(hash.count(c)) //如果前指针指向的元素在hash中,即是t的元素,
{ // 需要进去把他的次数-1,(因为要滑动窗口划过去了)
//缩小窗口的时候减1
hash[c]--;
}
//窗口缩小
slow++;
}
}
//找不到的情况
if(left == -1)
return"";
returnstring(S.begin() + left, S.begin() + (right + 1));
}
};