版权声明:由于一些问题,理论类博客放到了blogger上,希望各位看官莅临指教https://efanbh.blogspot.com/;本文为博主原创文章,转载请注明本文来源 https://blog.csdn.net/wyf826459/article/details/82885960
题目描述:
Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n).
Example:
Input: S = "ADOBECODEBANC", T = "ABC" Output: "BANC"
Note:
- If there is no such window in S that covers all characters in T, return the empty string
""
. - If there is such window, you are guaranteed that there will always be only one unique minimum window in S.
算法实现
核心思路是维护两个索引Start 和 End(初值都为0),分别标识子串的开始位置和结束位置,通过一系列操作找到所有能够涵盖T所有字符的子串,然后找到最短串。
具体的我们要建立一个哈希映射,保存T中各个字符和其出现次数的关系映射,另外建立一个count保存当前窗口内的有效字符数,通过while循环来实现,具体在每一个while循环内,在当前位置
- 首先如果没有找到T中的字符,end++,继续往后找,直到找到一个T中的字符(m.count(s[end]))。
- 如果找到了T中的字母,则该字符在m中映射的value--(表示找到一个,需要的该字符的数量减一),当然可能有字母重复数大于其在T中的数量,即value减为负了,这样找出来的window包含多余重复字母可能不是最优,所以当value为负值时这个值也是需要记录的,另外如果value减一后仍然大于零表明这个字符是有效字符,要让count++
- 一旦找满单词(count = T.length()),这个时候Start到End的位置肯定是包含目标T串所有字符的子串W(即Window)。具体还要对这个window进行优化
- 排除不在T中的字符(其实就是让Start执行步骤1中类似的操作),缩小window大小
- 另一个方面,就是当window中出现重复的字符,这时,map中该字符的value为负了,我们可以在保证value值为非正的情况下向前移动start。
- 当找到一个符合要求的窗口后要对start进行操作,将start前移至下一个有效字符处,在移动start之前,要将当前start处的有效字符对应的value++, 同时count --(因为start后移后,其原位置处的有效字符被剔除窗口外)
class Solution {
public:
string minWindow(string s, string t) {
if(s.length() < t.length() || t.empty())return "";
unordered_map<char, int> m;
for(auto c:t)m[c] ++;
int start = 0, end = 0, minstart = 0, minend = 0;
int count = 0;
int windowsize = -1, minwindowsize = INT_MAX;
while(end < s.length()){
while(end < s.length() && !m.count(s[end]))end ++;
m[s[end]] --;
if(m[s[end]] >= 0)
{
count ++;
if(count == t.length()){
while(start != end){
while(!m.count(s[start]))start ++;
if(m[s[start]] < 0){
m[s[start]] ++;
start ++;
continue;
}
else
break;
}
windowsize = end - start + 1;
if(minwindowsize > windowsize){
minwindowsize = windowsize;
minstart = start;
minend = end;
}
m[s[start]] ++;
start ++;
while(start < end && !m.count(s[start]))start ++;
count --;
}
}
end ++;
}
if(minwindowsize == INT_MAX)return "";
return s.substr(minstart, minwindowsize);
}
};