
求解代码
java
public String minWindow(String S, String T) {
// 记录当前窗口中各字符的出现次数
HashMap<Character, Integer> window = new HashMap<>();
// 记录T中各字符需要的出现次数
HashMap<Character, Integer> need = new HashMap<>();
// 统计T中每个字符的出现次数
for (char c : T.toCharArray()) {
need.put(c, need.getOrDefault(c, 0) + 1);
}
int left = 0, right = 0; // 滑动窗口的左右指针,[left, right) 左闭右开区间
int valid = 0; // 有效匹配数
int start = 0, len = Integer.MAX_VALUE; // 记录最小窗口的起始下标和长度,初始len为无穷大
// 右指针扩窗口 → 嵌套 左指针缩窗口
while (right < S.length()) {
char c = S.charAt(right); // 即将加入窗口的字符
right++; // 右指针右移,扩大窗口(左闭右开,先取字符再移指针)
// 若当前字符是T需要的字符,更新window表
if (need.containsKey(c)) {
window.put(c, window.getOrDefault(c, 0) + 1);
// 当window中该字符的次数 == need中需要的次数时,有效匹配数+1
if (window.get(c).equals(need.get(c))) {
valid++;
}
}
// 当窗口满足条件(包含T所有字符),开始收缩左指针,找最小窗口
while (valid == need.size()) {
if (right - left < len) { // 若当前窗口长度更小,更新start和len
start = left; // 记录最小窗口的起始下标
len = right - left; // 记录最小窗口的长度(左闭右开,长度=right-left)
}
char d = S.charAt(left); // 即将移出窗口的字符
left++;
// 若移出的字符是T需要的字符,更新window表和valid
if (need.containsKey(d)) {
// 若移出前该字符的次数刚好满足need,移出后会不满足,有效匹配数-1
if (window.get(d).equals(need.get(d))) {
valid--;
}
window.put(d, window.get(d) - 1); // 窗口中该字符次数-1
}
}
}
// 若len仍为无穷大,说明无满足条件的窗口,返回空串;否则返回最小子串
return len == Integer.MAX_VALUE ? "" : S.substring(start, start + len);
}
小贴士
因为滑动窗口是左闭右开区间 ,所有len的计算不用+1。