76. 最小覆盖子串
题目:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
解题思路:
这道题遍历s的子串的右端点right,如果子串涵盖t,则左端点left向右移动直到不涵盖t为止。在移动过程中更新最小子串的左右端点。
详细题解可看灵神题解https://leetcode.cn/problems/minimum-window-substring/solutions/2713911/liang-chong-fang-fa-cong-o52mn-dao-omnfu-3ezz
class Solution {public String minWindow(String s, String t) {if(s.length() < t.length()){return "";}int len_s = s.length();int ansLeft = -1, ansRight = len_s;Map<Character, Integer> cnt_t = new HashMap<>();Map<Character, Integer> cnt_sub = new HashMap<>();for(char c : t.toCharArray()){cnt_t.compute(c, (k, v) -> (v == null) ? 1 : v + 1);}int left = 0;for(int right = 0; right < len_s; right++){cnt_sub.compute(s.charAt(right), (k, v) -> (v == null) ? 1 : v + 1);while(isCovered(cnt_sub, cnt_t)){if(right - left < ansRight - ansLeft){ansLeft = left;ansRight = right;}cnt_sub.compute(s.charAt(left), (k, v) -> (v == null) ? 0 : v - 1);left++;}}return ansLeft < 0 ? "" : s.substring(ansLeft, ansRight + 1);}private boolean isCovered(Map<Character, Integer> map1, Map<Character, Integer> map2){for(char key : map2.keySet()){if(map1.getOrDefault(key, 0) < map2.get(key)){return false;}}return true;}
}