zoukankan      html  css  js  c++  java
  • Leetcode第76题:最小覆盖子串

    题目

    给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。

    示例:

    输入: S = "ADOBECODEBANC", T = "ABC"
    输出: "BANC"
    
    说明:
    如果 S 中不存这样的子串,则返回空字符串 ""。
    如果 S 中存在这样的子串,我们保证它是唯一的答案。

    题解

    解题思路来自于参考文章。本题采用一种高级双指针的滑动窗口法+哈希法进行求解。一般滑动窗口法适用于求解字符串匹配问题。具体解法见代码注释。

    class Solution {
        public String minWindow(String s, String t) {
            /*
                参考网上求解:
                本题采用滑动窗口法进行求解,利用左右指针维护窗口大小,具体算法流程如下:
                1.初始化左右指针left=right=0,利用双指针法得到一个窗口
                2.不断增加right值以向右滑动窗口,直到窗口中的字符串符合要求
                3.停止右指针的滑动,开始增加left指针值来缩小窗口大小,直到窗口中的字符串不符合题目要求为止,同时每次滑动left指针都记录好相关值以更新结果
                4.重复2、3步直到right到达被查找字符串末尾
    
                //注意这里用Integer作为计数值会出现bug,他是个对象,当用==判断时,他会判断地址,因为Integer只会缓存-128~127之间的数值,所以当超过这个区间的值后,就会new一个对象,出现地址不一致
            */
            if(s.length() < t.length()){
                return "";
            }
            int left = 0;
            int right = 0;
            Map<Character, Integer> need = new HashMap<>();
            Map<Character, Integer> window = new HashMap<>();
            int len = 0;
            int minLen = Integer.MAX_VALUE;    //记录最小长度
            int start = 0;    //记录最小长度在被查找字符串中的起始位置
            for(int i = 0; i < t.length(); ++i){
                int count = need.getOrDefault(t.charAt(i), 0);
                need.put(t.charAt(i), count + 1);
            }
            while(right < s.length()){
                char c = s.charAt(right);
                if(need.containsKey(c)){
                    int count = window.getOrDefault(c, 0);
                    window.put(c, count + 1);
                    if(window.get(c).intValue() == need.get(c).intValue()){    //这里如果不进行intValue()的话,会通过不了最后一个测试用例,原因见上面
                        len++;    //代表匹配了一个字符
                    }
                }
                right++;
                while(len == need.size()){    //开始上面的第3步,进行缩小滑动窗口
                    if(right - left < minLen){    //更新好最值
                        minLen = right - left;
                        start = left;
                    }
                    char c1 = s.charAt(left);
                    if(need.containsKey(c1)){
                        int count = window.get(c1);
                        window.put(c1, count - 1);
                        if(window.get(c1).intValue() < need.get(c1).intValue()){
                            len--;
                        }
                    }
                    left++;
                }
            }
            return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);
        }
    }

    参考

  • 相关阅读:
    一个tomcat设置多个端口,多个端口对应多个应用
    Docker 容器镜像删除
    Centos7上安装docker
    oracle锁表与解表
    windows共享文件夹
    tomcat部署项目后,war包是否可刪?war包存在必要性!
    解决Windows对JDK默认版本切换问题
    FLASHBACK介绍
    ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效
    Linux journalctl命令
  • 原文地址:https://www.cnblogs.com/jianglinliu/p/12005717.html
Copyright © 2011-2022 走看看