76. 最小覆盖子串(困难)
76. 最小覆盖子串
class Solution { public String minWindow(String s, String t) { //记录字符串当前s窗口中各字符的数量 HashMap<Character, Integer> hs = new HashMap<>(); //记录字符串t中各字符的数量 HashMap<Character, Integer> ht = new HashMap<>(); //先将ht填好 for(int i = 0; i < t.length(); i ++) ht.put(t.charAt(i), ht.getOrDefault(t.charAt(i), 0) + 1); //count记录当前窗口中满足t字符串的字符个数(必需字符),len记录符合条件的字串长度(取最小) //!!!len不能等与s.length(),因为第4步的判断条件是len > i - j + 1,当s=t时没有输出 int count = 0, len = s.length() + 1; String ans = ""; //[i, j]为滑动窗口 for(int i = 0, j = 0; i < s.length(); i ++){ //1.窗口右移了,更新hs中s[i]的value hs.put(s.charAt(i), hs.getOrDefault(s.charAt(i), 0) + 1); /* 2.ht中有新增的s[i]字符,并且hs中s[i]字符的数量 <= ht中s[i]字符的数量 * 表明窗口右移新增的字符s[i]是必需的,count++ * 注意此处有=号,不是<。原因是第1步已经更新了hs中的值,if中并不是<之后增加hs中的值,此处需要= */ if(ht.containsKey(s.charAt(i)) && hs.get(s.charAt(i)) <= ht.get(s.charAt(i))) count ++; /* 3.移动窗口左边界,必需满足j < i(左边界 < 右边界) * 如果字符串t中不包含s[j]字符,直接移动左边界 * 如果hs中s[j]的数量 > ht中s[j]的数量,也可以移动左边界 * 格式为while(a && (b || c)) */ while(j < i && (!ht.containsKey(s.charAt(j)) || hs.get(s.charAt(j)) > ht.get(s.charAt(j)))){ hs.put(s.charAt(j), hs.get(s.charAt(j)) - 1); // int tmp = hs.get(s.charAt(j)) - 1; // hs.put(s.charAt(j), tmp); j ++; } //4.必需字符达到了t的长度(条件满足),且长度比上次记录的小,更新数据 if(count == t.length() && len > i - j + 1){ len = i - j + 1; ans = s.substring(j, i + 1); } } return ans; } }