76.最小覆盖子串-hard

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

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

示例 1:

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

输入:s = "a", t = "a"
输出:"a"
 

提示:

1 <= s.length, t.length <= 105
s 和 t 由英文字母组成
 

思路:

  • 滑动窗口 + 左右指针(此题和 438 题类似);
  • 用一个 count 变量,来记录窗口内是否包含了 P 的字符;当同一字符出现多次时,只记录一次;
  • 当包含时,停下来检索窗口,慢慢缩小左边的窗口;
  • 直到其不能再缩小为止,记录答案即可。

class Solution {
    public String minWindow(String s, String t) {
        int[] arrT = new int[128]; // 有大小写字母,用 128 的数组
        int[] arrW = new int[128]; //滑动窗口
        for(char c : t.toCharArray()) arrT[c]++;
        int left = 0, right = 0, count = t.length();
        String res = "", tmpStr = "";
        while(right < s.length()){
            char cr = s.charAt(right); // char 字符在Java中是数字,在128的数组中可以直接使用
            right++;
            if(arrT[cr] > 0){ //是 t 中存在的字符
                arrW[cr]++; // 滑动窗口累加一次
                if(arrW[cr] <= arrT[cr]) count--; //在标准 t 的范围之内,count--
            }
            while(count == 0){ // count = 0 说明窗口内,必定包含 t 的字符串,尽可能缩小窗口
                char cl = s.charAt(left);
                if(arrT[cl] > 0){ //窗口左边的字符,存在于 t 中
                    arrW[cl]--; //窗口累减一次
                    if(arrW[cl] < arrT[cl]){ //如果减了过后,窗口中的字符个数,小于标准值了
                        tmpStr = s.substring(left, right); //说明不能再缩小了
                        count++; // count 累加
                    }
                }
                left++; //移动窗口左边指针
            }
            if(tmpStr.length() > 0){ //比较是否更新答案
                if(res.length() == 0) res = tmpStr;
                else if(tmpStr.length() < res.length()) res = tmpStr;
            }
        }
        return res;
    }
}
原文地址:https://www.cnblogs.com/luo-c/p/13937357.html