76. 最小覆盖子串
Tag String
Two Pointers
Sliding Window
Difficulty Hard
Link https://leetcode-cn.com/problems/minimum-window-substring/
分析
有一类题型可以用滑动窗口的框架来解决,这是一种双指针的思想。
思路:
- 初始化左右指针
left=right=0
,区间[left, right]
就是一个窗口 - 不断增加
right
,扩大窗口,直到窗口符合题目要求(本题中是包含T中所有字母) - 然后不断增加
left
,缩小窗口,直到窗口不符合题目要求。每次增加,都要更新结果 - 重复上述两步,直到
right
到达字符串末尾
Tip:第二步寻找可行解,第三步寻找最优解
题解
class Solution {
public String minWindow(String s, String t) {
int left=0;
int right=0;
// 记录最短字符的起始位置和长度
int start=0;
int minlen=Integer.MAX_VALUE;
// 记录字符和对应的数量,计数器
HashMap<Character,Integer> needs=new HashMap<>();
HashMap<Character,Integer> window=new HashMap<>();
for (Character c : t.toCharArray()) needs.put(c, needs.getOrDefault(c, 0) + 1);
int match=0;
while(right<s.length()){
char c1=s.charAt(right);
if(needs.containsKey(c1)){
window.put(c1,window.getOrDefault(c1,0)+1);
// 字符数量一致,匹配数加1
if(window.get(c1).compareTo(needs.get(c1))==0)
match++;
}
// 扩大窗口
right++;
while(match==needs.size()){
if(right-left<minlen){
start=left;
minlen=right-left;
}
char c2=s.charAt(left);
if(needs.containsKey(c2)){
window.put(c2,window.get(c2)-1);
if(window.get(c2)<needs.get(c2))
match--;
}
// 缩小窗口
left++;
}
}
return minlen==Integer.MAX_VALUE ? "":s.substring(start,minlen+start);
}
}