题目
java实现
class Solution {
public String minWindow(String s, String t) {
HashMap<Character, Integer> needs = new HashMap<>();
HashMap<Character, Integer> window = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
//needs中key为t中的字符,value为该字符的个数
char c = t.charAt(i);
needs.put(c, needs.getOrDefault(c, 0) + 1);
}
int left = 0;
int right = 0;
int valid = 0; //记录有效个数
//最小覆盖子串的起始索引及长度
int start = 0;
int len = Integer.MAX_VALUE;
while (right < s.length()) {
//移动right,扩大窗口,c是将要进入窗口的字符
char c = s.charAt(right++);
//更新窗口数据
if (needs.containsKey(c)) {
window.put(c, window.getOrDefault(c, 0) + 1);
if (window.get(c).equals(needs.get(c)))
valid++;
}
//判断左窗口是否要收缩
while (valid == needs.size()) {
if (right - left < len) {
//当前子串长度比上一个子串短
start = left;
len = right - left;
}
//remove是将移出窗口的字符
char remove = s.charAt(left++);
//更新窗口数据
if (needs.containsKey(remove)) {
if (window.get(remove).equals(needs.get(remove)))
valid--;
//remove个数减一
window.put(remove, window.get(remove) - 1);
}
}
}
return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len);
}
}
思路解析
- 本题创建了两个HashMap对象,分别是
needs
和window
,needs
用来存储字符串t
的每个字符及其个数,window
用来存储窗口范围内在needs
中出现的字符及其个数。 - 初始化左右指针,
right
先出发,向右移动,每移动一次检查needs
中是否存在新进入窗口的字符,如果存在,则把该字符加入window
中,然后window
和needs
比较该字符存在个数,如果相等,则有效值valid
加一。 - 如果有效值
valid
等于needs
的长度,即窗口中的子串s1
满足题意,此时缩小子串,left
向右移动,如果缩小后的子串满足valid == needs.size()
,则更新子串的起始索引和长度。 - 退出循环后,如果
len == Integer.MAX_VALUE
,则不存在该子串,返回""
,否则返回该子串。
注意事项:
由于根据key,返回字符个数的类型是Integer,所以要使用equals()
方法进行比较,不能简单的使用==
比较。(Integer判断是否相等的坑)