[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

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2014-11-28 05:13  A_zhu  阅读(2800)  评论(1编辑  收藏  举报