【算法题解】76. 最小覆盖子串 - Java - 滑动窗口

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

注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。

 

示例 1:

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

输入:s = "a", t = "a"
输出:"a"
Java代码
    // 滑动窗口
    public String minWindow(String s, String t) {
        // 窗口的左边界
        int l = 0;
        // 窗口的右边界
        int r = 0;
        // 记录窗口中符合字符的个数
        int valid = 0;
        // 记录最小覆盖字串的起始索引及长度
        int start = 0, len = Integer.MAX_VALUE;
        // 窗口里符合的字符
        HashMap<Character,Integer> window = new HashMap<>();
        // 需要的字符
        HashMap<Character,Integer> needs = new HashMap<>();
        
        // 记录t中字符出现的次数
        for (char c : t.toCharArray()) {
            needs.put(c,needs.getOrDefault(c, 0) + 1);
        }

        while (r < s.length()) {
            // 扩大窗口
            char c = s.charAt(r);
            r++;
            
            // 更新窗口的数据
            if (needs.containsKey(c)) {
                // 若当前字符是满足条件的,则更新窗口window中字符出现的次数,
                window.put(c, window.getOrDefault(c, 0) + 1);
                // 若遇到了存在的字符则窗口中字符的总次数加一
                if (window.get(c).equals(needs.get(c))) {
                    valid++;
                }
            }
            
            // 满足条件(出现了需要的全部的字符即valid满足了),则缩小窗口
            while (valid == needs.size()) {
                // 计算窗口的长度。比较当前窗口的长度和上一个窗口的最小长度,若当前窗口的长度更小则更新最小长度,否则不更新,
                if (r - l < len) {
                    // 窗口开始的下标,
                    start = l;
                    len = r - l;
                }
                
                // 开始缩小窗口
                char lChar = s.charAt(l);
                l++;
                
                // 更新窗口内的值
                if (needs.containsKey(lChar)) {
                    // 若左边的字符是needs中的,则窗口的window中字符出现的次数减一,因为要移除左边的字符
                    if (needs.get(lChar).equals(window.get(lChar))){
                        valid--;
                    }
                    // 移除窗口中window的字符出现次数
                    window.put(lChar,window.getOrDefault(lChar, 0) - 1);
                }
            }
        }
        // len 判断是否存在,不存在返回空,存在则截取s
        return len == Integer.MAX_VALUE ? "": s.substring(start, start + len);
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值