This is suppose to be an easy question since I have already read through stormrage's post and thought I have mastered every detail about this code. But eventually it took me almost 3 hours straight to figure out a nice and clean code.
There are several things that one should notice in designing a robust algorithm for this problem:
- loop invariant: count <= total required chars. (excessive chars not accounted). If count < total required chars, we are building the first matching window. thus shrinking left edge is not necessary. Else if count == total required chars, Current window is either a half finished first time window or perfect left edge window with "one extra required char on the right edge " window. In both cases we can start shrinking left edge.
- We do not have to write a separate code block to do first time window matching because either the first matching or second matching requires left shrinking. Thinking of S = "aab" and T = "b".
So eventually with some modifications I come up with the following code. Alas, always think carefully before you start coding.
string minWindow(string S, string T) {
if(S.size() < T.size() || !T.size()) return *(new string);
vector lmt(256);
for(auto c:T) lmt[c]++;
vector ct(256);
int minLen = INT_MAX;
string ret;
int a0, a1, count; // left and right edge pointer.
count = 0;
for(a0 = 0, a1 = 0; a1 < S.size(); a1++) { // do right edge expand at loop start
if(!lmt[S[a1]]) continue; // invalid char, keep expanding
if(ct[S[a1]] < lmt[S[a1]]) count++; // char is needed now, increase count
ct[S[a1]]++; // hasFound array+1
if(count == T.size()) { // loop invariant met, now do shrinking
for(;a0 < a1; a0++) { // shrinking....
if(!lmt[S[a0]]) continue; // invalid char, keep shrinking
ct[S[a0]] --; // good char, try hasFound--
// before shrinking
if(ct[S[a0]] < lmt[S[a0]]) { // oops, should not delete this char.
ct[S[a0]]++; // roll hasFound back.
break; // don't move left edge pointer a0
} // it's ok to remove this char, keep
// shrinking
}
if(a1 - a0 + 1 < minLen) { // one min window found. update
minLen = a1-a0+1;
ret = S.substr(a0, a1-a0+1);
}
}
}
if(minLen == INT_MAX) return *(new string); // INT_MAX is acting as safeguard.
return ret;
}
No comments:
Post a Comment