解题思路:
滑动窗口问题,其实框架还是很明显的,具体浏览一下注释。
此题为窗口左右下标交替增加。
配合一下滑动窗口其他题。如下:
3. 无重复字符的最长子串
class Solution {
public String minWindow(String s, String t) {
HashMap <Character, Integer> need = new HashMap<>(); // 记录需要凑齐的char
HashMap <Character, Integer> window = new HashMap<>();//记录窗口中的char
//把t中的字符加入,need种
for(int i = 0;i < t.length(); i++){
need.put(t.charAt(i),need.getOrDefault(t.charAt(i),0)+1); //例如:{A:1,B:1,C:1}
}
int left = 0, right = 0; //滑动窗口左右下标
int valid = 0;//记录符合要求的字符
int start = 0;//记录最小覆盖字串起始索引
int len = Integer.MAX_VALUE;//记录最小覆盖字串起始长度
while(right < s.length()){
char c = s.charAt(right); // c是将移入窗口的字符
right++;//窗口右下标先增长
//对窗口进行更新
if(need.containsKey(c)){
window.put(c,window.getOrDefault(c,0)+1);
if(window.get(c).equals(need.get(c))){
valid++;
}
}
//判断窗口的左下标是否要收缩,如果找到的need中的字符串与valid计数相同说明找到了覆盖的字符串,
//但是还有一种情况可能字符串有重复,所以左下标要更新收缩,去找到最小覆盖的子串
while(valid == need.size()){
if(right - left < len){
len = right - left;
start = left;
}
//d是将要移出窗口的字符
char d = s.charAt(left);
//收缩窗口左下标
left++;
//当left移动到窗口中的char与need中的不同时,右下标继续移动,重复上面的过程,知道右下标到达字符串末尾
if(need.containsKey(d)){
if(window.get(d).equals(need.get(d))){
valid--;
}
window.put(d,window.get(d)-1);
}
}
}
//返回最小覆盖子串
return len == Integer.MAX_VALUE ? "" : s.substring(start, start+len);
}
}