前言
兄弟们,互联网寒冬期,算法刷着走。上篇文章讲了双指针的左右指针,双指针是数组类算法题中最重要的一个分支之一。这篇文章讲双指针技巧的滑动窗口。遇到双指针的题目,直接套用模板就完事儿。另外,数组有下图这些知识点与技巧。
思路
滑动窗口一般用于解决主串是否满足子串的某些需求问题,比如,是否包含某个字串,是否含有字串的所有字符等。
滑动窗口有固定的解题模板。但是细节众多,需要反复练习。
//s为原字符串,t为子字符串
public void slidingWindow(String s, String t) {
//初始化窗口应该满足的条件needMap,key=子串t中的字符,value=字符在t字符串中出现的次数
Map<Character, Integer> needMap = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
Character k = t.charAt(i);
needMap.put(k, needMap.getOrDefault(k, 0) + 1);
}
//滑动窗口中包含的字符,及其数量,key=滑动窗口中的字符,value=字符出现的次数
Map<Character, Integer> winMap = new HashMap<>();
//l:窗口左指针,r窗口右指针,validCount:窗口中有多少个字符满足了条件。
int l = 0, r = 0, validCount = 0;
while (r < s.length()) {
//即将加入窗口的字符
char in = s.charAt(r);
//窗口右指针右移
r++;
//进行窗口内数据的操作
...
while (窗口是否应该收缩) {
//即将从窗口移除的字符
char out = s.charAt(l);
//窗口左指针右移
l++;
//进行窗口内数据的操作
...
}
}
}
最小覆盖子串
解题思路
套用滑动窗口模板。窗口左右指针下标从0开始遍历原字符串。
窗口的右指针右移后,判断加入窗口的字符是否是子串的字符,若是则更新winMap。更新后若winMap中该字符的value=needMap中该字符的value,说明滑动窗口中该字符数量与子串该字符的数量相等,则validCount+1。
当validCount=needMap.size()时,说明子串中的字符全部都包含在了滑动窗口中,且每个字符的字符数量也满足。这时就把窗口的左指针右移,直到窗口中的字符串不在符合要求为止。
重复上诉步骤,找出最小的窗口。
复杂度分析