leetcode 76. Minimum Window Substring
link
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 empty string ""
.
If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.
題意:
設T裏的字符i有aim[i]個,在S中求最短子串X, 使得X中的字符i有now[i]個且滿足對任意i有now[i] >= aim[i]。 保證最短的子串只有一個。
思路:
和之前那個concate一個思路,其實也是維護一段窗口內的信息。
變化的地方只在於,裏面有多余的字符也沒有關系。
因此對於右端,一個新加入的字符s[i], 首先肯定是要加進去的。
如果s[i]出現在aim中,則其的加入可能可以使得now[i] > aim[i], 也就是我們可以從左端消除一些字符。 因此用一個while條件判斷左端是否滿足now[s[left]] > aim[s[left]]的條件, 滿足的話刪去左端點是沒有問題的。
在實現的時候偷了個懶,用aim直接計算目前窗口中的數量和目標數量的差距,也就是aim = aim - now。並且只維護起始的aim不為零的部分。那麽while的條件就變為了aim[s[left]] < 0
在統計是否所有的i都成立的時候,註意我們加入一個i的時候有三種情況。
1. i再加一個就滿足了aim[i] <= now[i]的情況。也就是說此時now[i} = aim[i] - 1, 用我們的統計方法也就是aim[i] = 1, 加入後aim[i]恰好變為0
2. i加入多於目標個了,也就是now[i] >= aim[i] , (aim[i] <= 0) 加入 後消除aim等號,變為aim[i] < 0
3 加入i也不夠aim[i], 也就是aim[i] > 0
因此只有在加入i後aim[i]變為0,才能使一個新的i成立。 統計aim中非零的數量,在aim[i] = 0時更新計數器,直至所有i成立,為第一個可行解。當第一個可行解出現後,用我們更新窗口的方法後面的所有情況都是可行的。
code:
class Solution { public: string minWindow(string s, string t) { string ans = ""; int nowMinLength = INT_MAX; unordered_map<char, int> aim; int charCount = 0; for(int i = 0; i < t.length(); i++){ if(aim.count(t[i]) == 0) charCount ++; aim[t[i]] ++; } int left = 0, cnt = 0; for(int i = 0; i < s.length(); i++){ //if(aim.count(s[i]) == 1){ aim[s[i]] --; if(aim[s[i]] == 0) cnt ++; while(aim[s[left]] < 0 && left < i){ aim[s[left]] ++; left ++; } if(cnt == charCount){ int tmpLen = i - left + 1; if(tmpLen < nowMinLength){ nowMinLength = tmpLen; ans = s.substr(left, tmpLen); } } //} } return ans; } };
leetcode 76. Minimum Window Substring