[LeetCode] Minimum Window Substring 散列映射問題


題目:


 

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 emtpy string "".

If there are multiple such windows, you are guaranteed that there will always be only one unique minimum window in S.

 

Hide Tags
  Hash Table Two Pointers String
     在字符串 S 中查找最小的窗口,使窗口中全部包含字符串T 中的字符,(不按順序),需要注意的地方:
  • T 中的字符可以重復,窗口需要重復包含。
  • 測試 實驗中的是SCII字符 ,所以可以用128位數組代替 hash table。
  • leetcode  c++ 中不能用 hash_map。

思路:

  1. 使用一個映射int need(hash table 或者 128位數組) 存儲T中個字符需要的個數,因為需求可能為負,所以用int。
  2. 使用一個映射bool exitst(hash table 或者 128位數組) 存儲T中個字符是否存在,使用hashtable 也構造這個,因為find 是遍歷查找的。
  3. 用一個var 記錄窗口中符合T 中char 的個數。
  4. 用下表start、last 標記窗口位置,start 指向窗口內第一個char,last 指向窗口外右邊第一個char(包括結尾)。
  5. 每次循環加入或刪除(記錄一個flag)一個字符,如果不存在便繼續循環。
  6. 通過判斷加入刪除flag進行操作,更新need 表,更新var, 如果等於T 的長度,更新返回記錄。
  7. 循環結束判斷能否查找。
 下面是我寫的,需要的時間復雜度為O(length(S)),即O(n),空間復雜度為O(length(T)):
 1 #include <string>
 2 #include <hash_map>
 3 #include <iostream>
 4 #include <map>
 5 using namespace std;
 6 using namespace __gnu_cxx;
 7 
 8 class Solution {
 9 public:
10     string minWindow(string S, string T) {
11         int numS = S.length(),numT = T.length();
12         if(numS<1||numT<1)    return "";
13         int WinStart=0,WinLast=0,WinCount =0,retStart,leng=INT_MAX;
14         hash_map<char, int > need;
15         hash_map<char, bool > exist;
16         for(int i =0;i<numT;i++){
17             need[T[i]]++;
18             exist[T[i]] = true;
19         }
20 
21         bool addorminus;
22         char curchar;
23         while(WinStart<=numS-numT){
24             if(WinCount!=numT&&WinLast<numS){
25                 addorminus = true;
26                 curchar = S[WinLast++];
27             }
28             else{
29                 addorminus = false;
30                 curchar = S[WinStart++];
31             }
32             if(!exist[curchar]) continue;
33             if(addorminus){
34                 if(need[curchar]>0)  WinCount++;
35                 need[curchar]--;
36                 if(WinCount==numT&&leng>WinLast - WinStart){
37                     retStart = WinStart;
38                     leng = WinLast - WinStart;
39                 }
40             }
41             else{
42                 if(WinCount==numT&&leng>WinLast - WinStart+1){
43                     retStart = WinStart-1;
44                     leng = WinLast - WinStart+1;
45                 }
46                 need[curchar] ++;
47                 if(need[curchar]>0)  WinCount--;
48             }
49         }
50         if(leng==INT_MAX)
51             return "";
52         return S.substr(retStart,leng);
53     }
54 };
55 
56 int main()
57 {
58     string s = "1A123BAC1";
59     string t = "AABC";
60     Solution sol;
61 
62     string ret = sol.minWindow(s,t);
63     cout<<ret<<endl;
64     return 0;
65 }
View Code

 

 leetcode 討論里面有另外一個實現,也是O(n),實現類似,不同的是循環內是通過判斷窗口中已經有T中字符的個數來進行 add or delete,我寫的是通過目標操作字符來進行,邏輯上沒有ta寫的方便。
 https://oj.leetcode.com/discuss/10337/accepted-o-n-solution
 
 
 1 class Solution {
 2 public:
 3     string minWindow(string S, string T) {
 4         if (S.empty() || T.empty())
 5         {
 6             return "";
 7         }
 8         int count = T.size();
 9         int require[128] = {0};
10         bool chSet[128] = {false};
11         for (int i = 0; i < count; ++i)
12         {
13             require[T[i]]++;
14             chSet[T[i]] = true;
15         }
16         int i = -1;
17         int j = 0;
18         int minLen = INT_MAX;
19         int minIdx = 0;
20         while (i < (int)S.size() && j < (int)S.size())
21         {
22             if (count)
23             {
24                 i++;
25                 require[S[i]]--;
26                 if (chSet[S[i]] && require[S[i]] >= 0)
27                 {
28                     count--;
29                 }
30             }
31             else
32             {
33                 if (minLen > i - j + 1)
34                 {
35                     minLen = i - j + 1;
36                     minIdx = j;
37                 }
38                 require[S[j]]++;
39                 if (chSet[S[j]] && require[S[j]] > 0)
40                 {
41                     count++;
42                 }
43                 j++;
44             }
45         }
46         if (minLen == INT_MAX)
47         {
48             return "";
49         }
50         return S.substr(minIdx, minLen);
51     }
52 };
View Code

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM