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; } }