滑动窗口解决最小覆盖子串
https://leetcode.cn/problems/minimum-window-substring/
题干:难度:hard
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
- 滑动窗口的思想其实就是双指针的配合使用
- 本题我们将索引[left,right)所包含的区间定义为窗口
- 将left和right都初始化为0,由于左闭右开,此时窗口中是不包含任何的字符的,right右移表示扩大窗口,left右移表示缩小窗口
- right每次又移至完全包含t,才会触发窗口的缩小,因为本题的目的就是寻求包含t的最短的子串(区别于子序列!)
- 扩大和缩小窗口涉及窗口内的数据更新(注意我们可以只针对t中锁包含的字符进行更新)
见代码:
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 left=0;
int right=0;
int valid=0;
int len=Integer.MAX_VALUE;
//还差一个start
int start=0;
while(right<s.length()){
char expect=s.charAt(right);//即将放入窗口中的字符
//先扩大窗口
right++;
//扩大了窗口之后,应需要更新数据:窗口内的数据,以及valid
if(need.containsKey(expect)){
//更新窗口中的数据
window.put(expect,window.getOrDefault(expect,0)+1);
if(window.get(expect).equals(need.get(expect))){
valid++;
}
}
//判断是否要收缩窗口(也就是尝试优化)
while(valid==need.size()){
if(right-left<len){
start=left;
len=right-left;
}
char del=s.charAt(left);
left++;
if(need.containsKey(del)){
if(window.get(del).equals(need.get(del))){
valid--;
}
window.put(del,window.get(del)-1);
}
}
}
return (len==Integer.MAX_VALUE)?"":s.substring(start,start+len);
}
}
文章评论