zoukankan      html  css  js  c++  java
  • Leetcode 76题:最小覆盖子串 滑动窗口经典题

    题目:给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。https://leetcode-cn.com/problems/minimum-window-substring/

    代码如下,记录一下:(引用 leetcode “垃圾代码制造者”,感谢!!!)

        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 left = 0, right = 0, valid = 0;
            // valid是用来记录窗口中满足need要求的字符和数量的数目,比如need中要求字符a数量为2,
            // 如果window中的a字符的数量等于了2,valid就+1,反之-1
            int len = Integer.MAX_VALUE;  // 记录最小字串的长度
            int start = 0;  // 记录最小字串的起始位置
            while (right < s.length()) {
                char addChar = s.charAt(right);  // 即将要加入window的字符
                window.put(addChar, window.getOrDefault(addChar, 0) + 1);
                right++;
                // 如果加入的字符是need中要求的字符,并且数量已经达到了need要求的数量,则valid+1
                // 这里和下面都有个坑,window.get(addChar)和need.get(addChar)返回的都是对象,最好用.equals()方法比较大小
                if (need.containsKey(addChar) && window.get(addChar).equals(need.get(addChar))) {
                    valid++;
                }
                // 当window中记录的字符和数量满足了need中要求的字符和数量,考虑缩窗口
                while (valid == need.size()) {
                    // 先判断当前的最小覆盖字串是否比之前的最小覆盖字串短
                    if (right - left < len) {  // 注意,这里上面已经对right实施了++操作,所以这里的长度不是right - left + 1
                        len = right - left;
                        start = left;  // 如果最短,则记录下该最小覆盖字串的起始位置
                    }
                    char removeChar = s.charAt(left);
                    // 开始缩减窗口,left右移,如果要从window删除的字符正好是need中需要的并且,数目也等于need中需要的数目,则删减后,该该字符要求的数量
                    // 显然不满足need要求的数量,所以valid要-1;
                    if (need.containsKey(removeChar) && window.get(removeChar).equals(need.get(removeChar))) {
                        valid--;
                    }
                    window.put(removeChar, window.get(removeChar) - 1);
                    left++;
                }
            }
            // 如果最小覆盖字串的长度相对于定义时没变,则t不包含s中所有的字符,返回"",如果长度改变过,说明存在这样的最小覆盖字串,直接输出。
            return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);
        }
    

    类似的题还有:

    提供一个字符串S,以及无重复字符的子串t,求S中所有包含t的子串的个数(不需要判断顺序)。
  • 相关阅读:
    昨天晚上简单英文词典查询及排版系统写完了
    c函数 atoi() 将字符串转换为整型 kbhit() 检测是否有按键按下 区分bioskey()
    写了一个字典树
    用scanf清空缓冲区 对比fflush
    爬取千千小说 -- xpath
    第二十六篇 -- 去掉标题栏并自定义标题栏
    git clone 中途停止不动
    使用turtle库画一朵玫瑰花带文字
    正则爬取我要个性网的头像
    用Pygal画一个英雄能力的图
  • 原文地址:https://www.cnblogs.com/doufuyu/p/15481172.html
Copyright © 2011-2022 走看看