zoukankan      html  css  js  c++  java
  • 76. 最小覆盖子串

    题目

    给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

    注意:1.如果 s 中存在这样的子串,我们保证它是唯一的答案。2.最小子串中不仅需要包含t中出现的字符,字符出现的次数也有要求
     
    示例 1:

    输入:s = "ADOBECODEBANC", t = "ABC"
    输出:"BANC"

    示例 2:

    输入:s = "aa", t = "aa"
    输出:"aa"

    滑动窗口法

    很显然要使用滑动窗口法,但关键的问题是如何得知当前子串是否包含了t中所有字符
    可以使用一个计数器cnt:遍历right时HashMap 中的 value 减一,如果减1后仍大于等于0说明该字符在t中出现过,cnt 自增1;当cnt等于t长度时说明已经包含了t中所有字符,此时left右移,遍历left时HashMap 中的 value 加一,如果加1后大于0说明移出掉的是t中出现的字符,cnt自减1。

    具体步骤:
    (1)先扫描一遍T,把对应的字符及其出现的次数存到 HashMap 中。
    (2)然后开始遍历S,就把遍历到的字母对应的 HashMap 中的 value 减一,如果减1后仍大于等于0,cnt 自增1。
    (3)如果 cnt 等于T串长度时,开始循环,纪录一个字串并更新最小字串值。然后将子窗口的左边界向右移,如果某个移除掉的字母是T串中不可缺少的字母,那么 cnt 自减1,表示此时T串并没有完全匹配。

        public String minWindow(String s, String t) {
            if(s.length()<t.length()) return "";
            int left=0,right=0,sLen=s.length(),tLen=t.length(),cnt=0,minLen=Integer.MAX_VALUE,l=left,r=right;
            int[] charCount=new int[128];
            for(int i=0;i<tLen;++i) charCount[t.charAt(i)]++;
            while(right<sLen){
                //如果减1后的映射值仍大于等于0,说明当前遍历到的字母是T串中的字母,cnt自增1
                if(--charCount[s.charAt(right++)]>=0) cnt++;
                while(cnt==tLen){
                    if(minLen>right-left){
                        minLen=right-left;
                        l=left;
                        r=right;
                    }
                    //如果加1后的值大于0了,说明此时少了一个T中的字母,那么 cnt 值就要减1
                    if(++charCount[s.charAt(left)]>0) cnt--;
                    left++;
                }
            }
            return s.substring(l,r);
        }
    

    LeetCode 76.最小覆盖子串

  • 相关阅读:
    axios增加的自定义header,后端request取不到
    ExecutorService 线程池 (转发)
    Java ExecutorService四种线程池的例子与说明(转发)
    如何合理地估算线程池大小?(转发)
    什么是CPU密集型、IO密集型?(转发)
    成功的唯一秘诀——坚持最后一分钟
    人生最精彩的不是实现梦想的瞬间,而是坚持梦想的过程
    贵在坚持
    第一个flask程序
    认识web
  • 原文地址:https://www.cnblogs.com/Frank-Hong/p/14752481.html
Copyright © 2011-2022 走看看