当前位置 博文首页 > LetJava的博客:Leetcode 76. 最小覆盖子串

    LetJava的博客:Leetcode 76. 最小覆盖子串

    作者:[db:作者] 时间:2021-09-03 18:18

    题目

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

    示例:

    输入: S = “ADOBECODEBANC”, T = “ABC”
    输出: “BANC”

    说明:

    • 如果 S 中不存这样的子串,则返回空字符串 “”。
    • 如果 S 中存在这样的子串,我们保证它是唯一的答案。

    解答

    使用滑动窗口算法思想。

    滑动窗口问题通用模板如下(本文章的重点内容!)
    int left = 0, right = 0;
    
    while (right < s.size()) {
        window.add(s[right]);
        right++;
        
        while (valid) {
            window.remove(s[left]);
            left++;
        }
    }
    

    本题步骤如下

    1. 先将 t 字符串的所有字符存入哈希表。
    2. 声明 lt, gt 两个指针作为滑动窗口 [lt, gt - 1] 的边界
    3. 此时如果窗口还不能匹配 t 的窗口, 让窗口扩大,gt ++ 。
    4. 若能匹配 t 的窗口, 统计最小子串,然后使窗口缩小,不断地让左边界 lt ++ ,直到不再覆盖 t 字串。

    tips:本题优化成 int[128] 代替 哈希表 效率会很高,但不太通用,我认为此优化学习不到啥,所以我没做。

    复杂度:O(S + T) 时间,O(S + T) 空间。

    本题代码

    class Solution {
        public String minWindow(String s, String t) {
            char[] ts = t.toCharArray();
            Map<Character, Integer> needs = new HashMap<>();
            for(char ch : ts) needs.put(ch, needs.getOrDefault(ch, 0) + 1);
            
            Map<Character, Integer> window = new HashMap<>();
            int lt = 0; int gt = 0;
            int start = 0; int end = s.length() + 1;
            int match = 0;
            while(gt < s.length()) {
                char c1 = s.charAt(gt);
                if(needs.containsKey(c1)) {
                    window.put(c1, window.getOrDefault(c1, 0) + 1);
                    if(window.get(c1).equals(needs.get(c1))) match ++;
                }
                
                gt ++;
                
                while(match == needs.size()) {
                    if(gt - lt < end - start) {
                        start = lt;
                        end = gt;
                    }
                    
                    char c2 = s.charAt(lt);
                    if(needs.containsKey(c2)) {
                        window.put(c2, window.get(c2) - 1);
                        if(window.get(c2) < needs.get(c2)) match --;
                    }
                    
                    lt ++;
                }
            }
                
            return end == s.length() + 1 ? "" : s.substring(start, end);
        }
    }
    

    结果

    在这里插入图片描述

    cs