解题记录 LeetCode 最小覆盖子串 滑动窗口较复杂题

题目链接: https://leetcode-cn.com/problems/minimum-window-substring/
题意: 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:如果 s 中存在这样的子串,我们保证它是唯一的答案。
**思路: ** 滑动窗口 维护哈希表 need 和 len, 思路不难, 写起来挺复杂的

class Solution {
    public String minWindow(String s, String t) {
        Map<Character,Integer> window = new HashMap();  //记录窗口中的字符和数量
        Map<Character,Integer> need = new HashMap();  // 需要的字符和数量
        // 造 need 
        for (int i = 0; i < t.length(); i++) {
            char needChar = t.charAt(i);
            need.put(needChar,need.getOrDefault(needChar,0)+1);
        }
        int l = 0,r = 0,valid = 0;
        // valid是用来记录窗口中满足need要求的字符和数量的数目
        int len = Integer.MAX_VALUE;  // 记录最小长度
        int start = 0;
        while(r < s.length()){
            char ccc= s.charAt(r);  // 即将要加入window的字符
            window.put(ccc,window.getOrDefault(ccc,0) + 1);  
            r++;
            // 如果加入的字符是need中要求的字符,并且数量已经达到了need要求的数量,则valid+1
            // 这里和下面都有个坑,window.get(ccc)和need.get(ccc)返回的都是对象,用.equals()方法比较大小, Integer 内部有对-128 ~ 127 的缓存
            if(need.containsKey(ccc) && window.get(ccc).equals(need.get(ccc))){
                valid++;
            }
			// 当数量满足, 缩窗口
            while(valid == need.size()){
                // 先判断当前的最小覆盖字串是否比之前的最小覆盖字串短
                if(r - l < len){  // 注意,这里上面已经对r实施了++操作,所以这里的长度不是r - l + 1
                    len = r - l ;
                    start = l;  // 如果最短,记录该最小覆盖字串的起始位置
                }
                char removeChar = s.charAt(l);
                // 开始缩减窗口,l右移
                if(need.containsKey(removeChar) && window.get(removeChar).equals(need.get(removeChar))){
                    valid--;
                }
                window.put(removeChar,window.get(removeChar) - 1);
                l++;
            }

        }
        // 如果最小覆盖字串的长度相对于定义时没变,则t不包含s中所有的字符,如果长度变过,则存在这样的最小覆盖字串
        return len == Integer.MAX_VALUE?"":s.substring(start,start+len);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值