最小覆盖子串
思路
可以用滑动窗口来解
- 右边界往右移动,移动到一个子串中包含的字符后停止
- 窗口中修改相应字符出现次数
- 如果此时窗口内包含所有子串字符,则开始修改左边界。
- 左边界移动,直到遇到到一个子串中包含的字符后停止
- 窗口中修改相应字符出现次数
统计窗口最小的长度就可以了
就像一个整体一直右移的弹簧,弹簧的左侧虽然抖动,但不影响最终到达终点
代码
class Solution {
public String minWindow(String s, String t) {
Map<Character, Integer> need = new HashMap<>();
Map<Character, Integer> window = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
need.put(t.charAt(i), need.getOrDefault(t.charAt(i), 0) + 1);
}
int right = 0, left = 0;
//valid就是t的长度
int valid = 0;
int start = 0, minLen = Integer.MAX_VALUE;
while (right < s.length()) {
char cur = s.charAt(right);
right++;
// 进行窗口数据一系列更新
//如果子串包含右边界
if (need.containsKey(cur)) {
Integer total = window.getOrDefault(cur, 0);
window.put(cur, total + 1);
if (window.get(cur).equals(need.get(cur))) {
valid++;
}
}
while (need.size() == valid) {
if (right - left < minLen) {
start = left;
minLen = right - left;
}
// d 是将移除窗口的字符串
char d = s.charAt(left);
// 左边移动窗口
left++;
// 进行窗口内数据当一系列更新
if (window.containsKey(d)) {
if (window.get(d).equals(need.get(d))) {
valid--;
}
window.put(d, window.get(d) - 1);
}
}
}
return minLen == Integer.MAX_VALUE ? "" : s.substring(start, start + minLen);
}
}