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.
分析:
由于大小写字母的ASCII码不大于128,因此开辟两个数组存储信息。
needFind数组存储T字符串每个字符出现次数。例如:needFind['A']=5意为T中A出现5次。
Found数组存储S字符串在[begin,end]窗口内每个字符出现次数。
算法核心思想如下:
在保证[begin,end]窗口包含T中所有字符的条件下,延伸end,收缩begin。
进行一次扫描后,记录符合条件的最小窗口(end-begin+1)表示的字符串。
有个问题:怎样才知道[begin,end]窗口包含了T中所有字符?
我使用count记录剩余“有效”字符数,当count达到0时,即可说明[begin,end]包含了T。
注意:“有效”的意思是指,当前延伸得到的S[end]字符,使得[begin,end]更进一步包含T,而不是重复劳动。
比如说,T="a", [begin,end]已经包含"a",再延伸得到"aa",只是无效操作,并没有使得[begin,end]更接近T,有效字符数仍为1.
ac代码:
class Solution {
public:
string minWindow(string s, string t) {
int begin=0,end=0,minbegin=0,minend=0,minsize=INT_MAX,size,s1=s.length(),s2=t.length(),i,j,c=s2;
vector<int>found(128,0);
vector<int>needfind(128,0);
for(i=0;i<s2;i++)
{
needfind[t[i]]++;
}
found[s[0]]++;
if(found[s[0]]<=needfind[s[0]])
{
c--;
}
while(1)
{
if(c==0)
{
while(found[s[begin]]>needfind[s[begin]])
{
found[s[begin]]--;
begin++;
}
size=end-begin+1;
if(minsize>size)
{
minbegin=begin;
minend=end;
minsize=size;
}
}
if(end<s1)
{
end++;
found[s[end]]++;
if(needfind[s[end]]>=found[s[end]])
c--;
}
else
{
break;
}
}
if(minsize!=INT_MAX)
{
return s.substr(minbegin,minsize);
}
else
return "";
}
};