zoukankan      html  css  js  c++  java
  • [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
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    【vue开发问题-解决方法】(十一)数据双向绑定导致修改数据格式原数据绑定出错
    【JavaScript】使用url下载文件,解决chrome浏览器自动识别图片打开问题。
    我的转行之路(电气转IT)------2018阿里校招面经
    关于Class.getResource和ClassLoader.getResource的路径问题
    protected修饰符详解
    为什么i=i++后,i的值不变(深入解析)
    Java中的初始化详细解析
    再谈抽象类(感觉理解的更深了)
    数据类型总结(干货)
    Java的接口和抽象类深入理解
  • 原文地址:https://www.cnblogs.com/Azhu/p/4127606.html
Copyright © 2011-2022 走看看