Minimum Window Substring
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 =
T =
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 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.
Analysis:
Generally speaking, the idea of this problem is not straightforward, implementation is not easy, it is a difficult problem!!!The idea is like this:
We have two pointers, p and q. S[p:q] stores the string covers all the chars in T. We want minimum p:q.
Start from the whole S, p=0, q=S.size()-1, if it cannot cover T, return "";
Fix p, try to move q close to p, but keep the requirement S[p:q] covers T.
Find the shortest p:q, here exactly is 1:q, where S[1:q] covers T.
Move p and q dynamically:
if S[p] is irrelevant char, p++;
if S[p] is char in T, must move q to left until find S[q]==S[p] to keep the requirement, or q is last.
When move q to left, if S[q] is in T, store the S[q] occurrence.
Every move, compare the length p:q store the minimum length and position.
To check if the S[p:q] covers T, because the complexity requirement, the idea goes as follows:
(1) use map<char, int>, to store the occurrence of chars in S and T. Be careful with the duplicate case.
(2) Check the occurrence of mapS and mapT, if mapS[T[i]]<mapT[T[i]], return false;
After find the first covered string [1:q], we do like one-by-one move, so the cover test can only be the occurrence of the first char S[p], and when move q, don't forget add occurrence if meets S[q] in T.
See code below for more details. Both small and large tests are passed
Code(201309):
class Solution { public: string minWindow(string S, string T) { // Start typing your C/C++ solution below // DO NOT write int main() function if (S.size()<T.size()){return "";} map<char,int>mp; // store chars occurrence of T for(int i=0;i<T.size();i++){mp[T[i]]++;} int res_len=INT_MAX; // result length int res_p=0;//result start posiion int p=0; //pointer start int q=S.size()-1; //pointer end while (mp[S[p]]==0){if(p>=S.size()){return "";} p++;} //remove irralevent starting chars while (mp[S[p]]==0){q--;if(q<0){return "";}} // remove irralevent ending chars map<char,int> tab; //store chars occurrence of S[p:q] for (int i=p;i<=q;i++){tab[S[i]]++;} while (tab[S[q]]>mp[S[q]] || mp[S[q]]==0){ // move q to left find the 1st covered substring tab[S[q]]--; q--; } for (int i=0;i<T.size();i++){ // if no covered substring found, return "" if (tab[T[i]]<mp[T[i]]){return "";} } if (q-p+1<res_len){res_len=q-p+1; res_p=p;} //store the result while (p<q){ if (q-p+1<res_len){res_len=q-p+1; res_p=p;} //store the result if (mp[S[p]]==0){p++;continue;} // if current char is not in T, go next if (tab[S[p]]>mp[S[p]]){tab[S[p]]--;p++;continue;} // if more chars in this substring, go next q++; while (q<S.size() && S[q]!=S[p]){ if (mp[S[q]]>0){tab[S[q]]++;} q++;} //move q to find a substring covers T if (q>=S.size()){q=S.size()-1;}else{tab[S[q]]++;} if (S[q]==S[p]){ tab[S[p]]--; if (tab[S[p]]<mp[S[p]]){break;} p++;continue;} break; } return S.substr(res_p,res_len); } };
check out my solution, clearer and better than yours :)
ReplyDeletestring minWindow(string S, string T) {
map counter;
map::iterator>> c;
list queue;
int remaining = T.length();
int minimumLength = INT_MAX;
string retValue = "";
for (char t : T) {
if (counter.count(t) == 0) {
counter.insert(pair(t, 0));
}
counter[t]++;
}
for (int j = 0; j < S.length(); j++) {
if (counter.count(S[j]) != 0) {
int i = counter[S[j]];
if (i == 0) {
auto i = c.at(S[j]).front();
queue.erase(i);
c.at(S[j]).pop();
} else {
counter[S[j]]--;
remaining--;
}
queue.push_back(j);
c[S[j]].push(--queue.end());
if (remaining == 0 && j - queue.front() < minimumLength) {
minimumLength = j - queue.front();
retValue = S.substr(queue.front(), minimumLength + 1);
}
}
}
return retValue;
}