LeetCode Hot 100 No.76最小覆盖子串

在这里插入图片描述
思路:
用滑动窗口的思路。
建立一个min=max_length保存最小字串长度。建立两个指针left 和 right ,一开始都指向字符串开头。然后用一个hashmap (名为window)保存窗口内容(字符—>该字符在窗口内出现的次数)。用一个hashmap保存t内容。
进入while循环,当right大于s.length()-1时,退出循环。

  • 首先判断窗口内是否刚好涵盖了t(t中的字符是否在窗口内而且还需要t中的每一个字符出现的次数与窗口内对应字符出现的次数相等)。
  • 如果没有涵盖t,则right右移一位。然后进入下一次循环。
  • 如果窗口正好涵盖了t (注意正好涵盖了t说明窗口内也包含t中所有字符且对应字符出现的数量正好相等,不能多),这时么我们就可以考虑右移left来缩减窗口的大小,来找到那个涵盖了t的最小子串。当left 的左移是将窗口内的元素从左到右逐渐移出的过程。每次我们右移left的时候都看一看这个left指向的元素是不是在 t 中,如果我们发现本次要移出的元素正好被 t 包含,那么说明从当前left为起点,到right所指向的位置就是s中的某一个涵盖t所有字符的最小字串,我们记录right-left+1为当前子串长度,并更新min。当right大于s.length()-1时,退出循环。

最后返回min。

class Solution {

    public String minWindow(String s, String t) {

        int n = s.length();
        HashMap<Character, Integer> tMap = new HashMap<>();
        HashMap<Character, Integer> windowMap = new HashMap<>();

        for (char c :  t.toCharArray()) { // 记录 t 中所有字符出现的次数

            tMap.put(c, tMap.getOrDefault(c, 0) + 1);
        }

        int left = 0, right = 0;
        // 记录窗口中满足条件的字符个数
        int flag = 0;

        // 记录最小覆盖字串的起始索引及长度
        int start = 0, minLength = Integer.MAX_VALUE;

        while (right < n) {

            char c = s.charAt(right);
            // 判断取出的字符是否在 t 中
            if (tMap.containsKey(c)) {

                windowMap.put(c, windowMap.getOrDefault(c, 0) + 1);
                // 判断取出的字符在窗口中的出现次数是否与 t 中该字符的出现次数相同
                if (windowMap.get(c).equals(tMap.get(c))) { 

                    flag++;
                }
            }

            // 判断是否需要缩小窗口(已经找到符合条件的子串)
            while (flag == tMap.size()) {

                if (right - left + 1 < minLength) {

                    start = left;
                    minLength = right - left + 1;
                }
                char c1 = s.charAt(left);
                left++;
                if (tMap.containsKey(c1)) {

                    if (windowMap.get(c1).equals(tMap.get(c1))) {

                        flag--;
                    }
                    windowMap.put(c1, windowMap.getOrDefault(c1, 0) - 1);
                }
            }
            right++;
        }
        return minLength == Integer.MAX_VALUE ? "" : s.substring(start, start + minLength);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值