题目:
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).
For example,
S = "ADOBECODEBANC"
T = "ABC"
Minimum window is "BANC"
.
Note:
If there is no such window in S that covers all characters in T, return the empty string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
思路:
这是一道典型的移动窗口问题。其基本思路是:首先统计t中的字符及其出现次数(由于题目要求时间复杂度为O(n),所以只能采用哈希表或者字符数组,才能在O(1)的时间复杂度内找到需要查找的字符),然后对字符串s进行一次遍历:采用num来表示目前尚未匹配的字符个数,一旦匹配到一个,则num减1,当num为0时,说明找到了一个全覆盖,则检查是否是最优解;接着从左边开始缩减不必要的字符,一旦发现左边字符是出现在t中的,则说明我们将来还要匹配这个字符,所以num增加1,重新开始拓展右边。
注意时间复杂度的分析:虽然在for循环内部又有while循环,但是while内部执行的总次数也不会超过n(因为left在这个过程中是严格递增的,递增次数最多为字符串s的长度),所以时间复杂度依然是O(n)。下面的代码采用了哈希表,实际上采用字符数组进行统计其运行效率会更高。
代码:
class Solution {
public:
string minWindow(string s, string t) {
unordered_map<char, int> hash;
int num = t.size(), len = INT_MAX, start = 0, left = 0;
for(auto val: t) // construct the hash table
hash[val]++;
for(int i = 0; i < s.size(); i++)
{
if(hash[s[i]]-- > 0) // we matched one character
num--;
while(num == 0) // we try removing the left characters
{
if(i - left + 1 < len) // we find a better cover
{
start = left;
len = i - left + 1;
}
if(hash[s[left++]]++ == 0) // we will miss this character
num++;
}
}
return len == INT_MAX ? "" : s.substr(start, len);
}
};