解題思路
很容易聯想到 sliding window,若該 window 中所有字母出現次數與希望的一樣,就看長度決定是否更新。
比對的方式則是該兩個 index array 以及 have 跟 need 兩個 int。index array 用來記錄該字母的出現次數,need 表示需要幾個「字母」種類(不考慮次數),have 表示現階段的 sliding window 有幾個「字母」(同樣不考慮次數)。
那要怎麼移動 sliding window?暴力解是 O(n^2) 的方法,也就是每個字母依序當開頭,然後每次就開頭 + 1、開頭 + 2的一路看到最後。但有時若已經 valid ,那就可以提前結束。
至此還可以進一步優化。當找到新的 valid window,可以回過頭把 left 往右移,一直到 invalid 為止,這麼做是因為可能前面包含到多餘的子字串。記得這個 pop 的動作也要檢查 have 是否要減少。
程式碼
class Solution { public: string minWindow(string s, string t) { if(t.size() > s.size()) return ""; int countS[128] = {0}, countT[128] = {0}, left = 0, right = 0; int have = 0, need = 0, minLen = s.size()+1, minL = 0, minR = 0; bool isFind = false; for(int i=0; i<t.size(); i++) { countT[t[i]]++; if(countT[t[i]] == 1) // meet first time need++; } while(right < s.size()) { // add right element into countS countS[s[right]]++; // check countS[i] == countT[i] ? // if true, have++ if(countS[s[right]] == countT[s[right]]) have++; // check have == need? // if true, update window len if needed // pop from front until have != need while(have == need) { if((right - left + 1) < minLen) { minLen = right - left + 1; minL = left; minR = right; isFind = true; } countS[s[left]]--; if(countS[s[left]] < countT[s[left]]) have--; left++; } right++; } if(!isFind) return ""; return s.substr(minL, minLen); } };
沒有留言:
張貼留言