参考博客 https://mp.weixin.qq.com/s/6YeZUCYj5ft-OGa85sQegw
思路:双指针,注意左右指针移动
模板:
public int slidingWindowTemplate(String[] a, ...) {
// 输入参数有效性判断
if (...) {
...
}
// 申请一个散列,用于记录窗口中具体元素的个数情况
// 这里用数组的形式呈现,也可以考虑其他数据结构
int[] hash = new int[...];
// 预处理(可省), 一般情况是改变 hash
...
// l 表示左指针
// count 记录当前的条件,具体根据题目要求来定义
// result 用来存放结果
int l = 0, count = ..., result = ...;
for (int r = 0; r < A.length; ++r) {
// 更新新元素在散列中的数量
hash[A[r]]--;
// 根据窗口的变更结果来改变条件值
if (hash[A[r]] == ...) {
count++;
}
// 如果当前条件不满足,移动左指针直至条件满足为止
while (count > K || ...) {
...
if (...) {
count--;
}
hash[A[l]]++;
l++;
}
// 更新结果
results = ...
}
return results;
}
几个比较经典的题目
思路:窗口大小是固定的,窗口长度就是输入参数中第二个字符串的长度,也就是说,右指针移动到某个位置后,左指针必须跟着一同移动,且每次移动都是一格,模版中 count 用来记录窗口内满足条件的元素,直到 count 和窗口长度相等即可更新答案。
2、最小覆盖子串
题目求的最小子串,也就是窗口的最小长度,说明这里的窗口大小是可变的,这里移动左指针的条件变成,只要左指针指向不需要的字符,就进行移动。
维护一个滑动窗口,窗口内的都是没有重复的字符,去尽可能的扩大窗口的大小,窗口不停的向右滑动。
-
(1)如果当前遍历到的字符从未出现过,那么直接扩大右边界;
-
(2)如果当前遍历到的字符出现过,则缩小窗口(左边索引向右移动),然后继续观察当前遍历到的字符;
-
(3)重复(1)(2),直到左边索引无法再移动;
-
(4)维护一个结果 res,每次用出现过的窗口大小来更新结果 res,最后返回 res 获取结果。
4、字符串的排列