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 emtpy string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
分析:
1.子问题“若子串和母串看作集合,子串是否属于母串子集”,使用num统计母串中出现子串的个数,int data[256]表来记录子串字符出现的个数。
首先遍历子串记录,将字符个数记录到data中例如data['x'] = 2。接着使用当前计数表int now[256]到母串中统计,若now[x] < data[x]时num++,若最后num等于子串的长度,那么表示子串属于母串的子集。
int data[256], now[256];
memset(data, 0, sizeof(data));
memset(now, 0, sizeof(now));
for(i = 0; i < T.size(); i++) {
data[T[i]]++;
}
for(i = 0; i < S.size(); i++) {
if(num < T.size()) {
if(now[S[i]] < data[S[i]]) num++;
now[S[i]]++;
}
if(num == T.size()) {
return true;
}
}
return false;
2.找到最小的窗口,这里可以使用前后指针j, i。i向前遍历,当j与i之间包含子串时,让j向前收缩,并统计本次的窗口结果。 接着让j往前走一步,进行下一次窗口计算。
class Solution {
public:
string minWindow(string S, string T) {
int i, j;
int data[250],now[250];
memset(data,0,sizeof(data));
memset(now,0,sizeof(now));
for(i=0;i<T.size();++i)
data[T[i]]++;
int left,right,min=INT_MAX,num=0;
for(i=0,j=0; i<S.size(); ++i) {
if(num < T.size()) {
if(now[S[i]] < data[S[i]]) num++;
now[S[i]]++;
}
if(num == T.size()) {
//收缩
while(j <=i && now[S[j]] > data[S[j]] ) {
--now[S[j]];
++j;
}
if(min > i - j + 1) {
left = j,right = i,min = i - j + 1;
}
//向前一步走
if(j < i) {
now[S[j]]--;
num--;
++j;
}
}
}
if(min != INT_MAX)return S.substr(left,right-left+1);
else return "";
}
};