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; } };