最小視窗子字串 LEETCODE 探索提升遇到的第一個困難的題目。
阿新 • • 發佈:2019-01-10
最小視窗子字串
給定一個字串 S 和一個字串 T,請在 S 中找出包含 T 所有字母的最小子串。
示例:
輸入: S = "ADOBECODEBANC", T = "ABC"
輸出: "BANC"
說明:
- 如果 S 中不存這樣的子串,則返回空字串
""
。 - 如果 S 中存在這樣的子串,我們保證它是唯一的答案
問題已經很具體了,分析ac程式碼。
class Solution { public: string minWindow(string s, string t) { vector<int> map(128,0); for(auto c: t) map[c]++; int counter = t.size(), begin = 0, end = 0, d = INT_MAX, head = 0; while(end<s.size()){ if(map[s[end++]]-- > 0) counter--; //in t while(counter == 0){ //valid if(end - begin < d) d = end - (head = begin); if(map[s[begin++]]++ == 0) counter++; //make it invalid } } return d==INT_MAX? "":s.substr(head, d); } };
定義ascII 128 字元hash 是在字串處理中,檢測是否出現過的常用做法。
通過第一行第二行程式碼確定了需要包含的字元範圍;我最初的想法是建立一個unorder_map 實質是一樣的。
對於字串處理這種方法更經濟直觀。
對於擷取子串來說。 在 counter 等於零的時候 ,
end 到 begin 一定是一條包含子串,這個時候 需要判斷是否是最短的子串。
長度就等 end - begin。先記錄下來。 然後在改變原先的map 現在需要的是繼續搜尋下一串子串,頭指標前移hash自加。但是問題是這樣不就不知道子串是不是包含t 了麼。依然是知道的。注意看if(map[s[end++]]-- > 0) counter--; //in t 這個程式碼。在這裡map中原來為1的變成了零,但是原來沒有的字元變成的是-1;在雜湊中就實現了不包含的字串就跳過了。當等於零的點在後一個迴圈中又出現時,說明包含的字元出現了,那麼給他自加到1,而沒有包含的字元從-1自加到零。counter 在自加1。跳出內層迴圈。同時相當於扔掉最早的出現的一個包含字元。尾部繼續搜尋最先出現的這個字元。
整個演算法拆開來就是這樣。 其中關鍵的有幾點
主迴圈只走一遍,end 在迴圈內無腦自加,同時利用hash檢測是否包含。同時又標記是否遍歷過。 記錄當前查詢進度
內層迴圈 主要功能 第一記錄當前找到的字串長度,與位置。第二,丟掉最先找到的包含字元,讓外迴圈繼續尋找這個字元在尾部。