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);
    }
}

参考

原文地址:https://www.cnblogs.com/jianglinliu/p/12005717.html