zoukankan      html  css  js  c++  java
  • 76. 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).

    Example:

    Input: S = "ADOBECODEBANC", T = "ABC"
    Output: "BANC"
    

    Note:

    • If there is no such window in S that covers all characters in T, return the empty string "".
    • If there is such window, you are guaranteed that there will always be only one unique minimum window in S.
       public class Solution {
            public String minWindow(String S, String T) {
                int[] srcHash = new int[255];
                // 记录目标字符串每个字母出现次数
                for(int i = 0; i < T.length(); i++){
                    srcHash[T.charAt(i)]++;
                }
                int start = 0,i= 0;
                // 用于记录窗口内每个字母出现次数 
                int[] destHash = new int[255];
                int found = 0;
                int begin = -1, end = S.length(), minLength = S.length();
                for(start = i = 0; i < S.length(); i++){
                    // 每来一个字符给它的出现次数加1
                    destHash[S.charAt(i)]++;
                    // 如果加1后这个字符的数量不超过目标串中该字符的数量,则找到了一个匹配字符
                    if(destHash[S.charAt(i)] <= srcHash[S.charAt(i)]) found++;
                    // 如果找到的匹配字符数等于目标串长度,说明找到了一个符合要求的子串    
                    if(found == T.length()){
                        // 将开头没用的都跳过,没用是指该字符出现次数超过了目标串中出现的次数,并把它们出现次数都减1
                        while(start < i && destHash[S.charAt(start)] > srcHash[S.charAt(start)]){
                            destHash[S.charAt(start)]--;
                            start++;
                        }
                        // 这时候start指向该子串开头的字母,判断该子串长度
                        if(i - start < minLength){
                            minLength = i - start;
                            begin = start;
                            end = i;
                        }
                        // 把开头的这个匹配字符跳过,并将匹配字符数减1
                        destHash[S.charAt(start)]--;
                        found--;
                        // 子串起始位置加1,我们开始看下一个子串了
                        start++;
                    }
                }
                // 如果begin没有修改过,返回空
                return begin == -1 ? "" : S.substring(begin,end + 1);
            }
        }

    转自 https://www.jianshu.com/p/ce80b4c07c22

    解题思路其实就是通过双指针维持一个Window,窗口右指针向右扩张用来找到包含子串为目的,窗口左指针向右收缩以使子串最小。
    典型的滑动窗口方法的实现。

     sliding window,换了一种好理解的方式:

    class Solution {
        public String minWindow(String s, String t) {
            if (s.isEmpty()) return "";
            if (s.length() < t.length()) return "";
            //src stores how many times char in t shows up.
            int src[] = new int[256];
            for(int i = 0; i < t.length(); i++) src[t.charAt(i)]++;
            //minwidth is the width of minimum string in S which contains T.
            int minwidth = Integer.MAX_VALUE;
            //win stores how many times char in s shows up, only store those exist in T.
            int win[] = new int[256];
            int length = 0; //The variable shows how many chars in t has shown in s.
            int wndstart = 0;   //window start position.
            int minstart = 0;   //minimum window start position.
            for(int i = 0; i < s.length(); i++){
                if(src[s.charAt(i)] > 0){
                    win[s.charAt(i)]++;
                    //To ensure the frequency of a certain char in s not more than in t.
                    if(win[s.charAt(i)] <= src[s.charAt(i)]) length++;
                }
                if(length == t.length()){
                    //Shorten the meaningless char at the beginning.
                    while(src[s.charAt(wndstart)] < win[s.charAt(wndstart)] || src[s.charAt(wndstart)] == 0){
                        win[s.charAt(wndstart)]--;
                        wndstart++;
                    }
                    if(minwidth > (i - wndstart + 1)){
                        minwidth = (i - wndstart + 1);
                        minstart = wndstart;    //Refresh minstart.
                    }
                }
            }
            return minwidth == Integer.MAX_VALUE ? "" : s.substring(minstart, minstart+minwidth);
        }
    }

     上面不要看

    class Solution {
        public String minWindow(String s, String t) {
            int [] map = new int[128];
            for (char c : t.toCharArray()) {
              map[c]++;
            }
            int start = 0, end = 0, minStart = 0, minLen = Integer.MAX_VALUE, counter = t.length();
            while (end < s.length()) {
              final char c1 = s.charAt(end);
              if (map[c1] > 0) counter--;
              map[c1]--;//如果c1存在于t,本来大于0减减后最多等于0,如果不存在,本来等于0减减后会小于0,
              end++;
              while (counter == 0) {
                if (minLen > end - start) {
                  minLen = end - start;
                  minStart = start;
                }
                final char c2 = s.charAt(start);
                map[c2]++;//还回去
                if (map[c2] > 0) counter++;//如果不存在,还回去最多 == 0,如果m【start】存在于t,那就有可能大于0,所以有此判断
                start++;
              }
            }
    
            return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLen);
          }
    }

    https://leetcode.com/problems/minimum-window-substring/discuss/26808/here-is-a-10-line-template-that-can-solve-most-substring-problems

  • 相关阅读:
    资金平台交易明细扩展开发-DEP
    固定资产清理之源码研究
    后台事务开发之简单示例
    mbos之动态图表设计
    协同附件上传源代码研究
    EAS集锦
    扩展报表-JavaSet
    mogoDB 4.2.0安装部署及JAVA 客戶端应用
    kafka 2.12在linux下的安装部署及java客户端对接
    nginx: the "ssl" parameter requires ngx_http_ssl_module in /usr/local/nginx/conf/nginx.conf
  • 原文地址:https://www.cnblogs.com/wentiliangkaihua/p/10522441.html
Copyright © 2011-2022 走看看