一.什么是滑动窗口
滑动窗口是一种双指针算法,基本思路为维护一个窗口,然后从前往后遍历元素进行运算。
//我做这类文档一个重要的目的还是给正在学习的大家提供方向(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非常非常高滴!!
共勉!!!
二.在题目中掌握思想(代码中会有注释)
ps:题目均选自力扣
1.长度最小的子数组
题目链接:209. 长度最小的子数组 - 力扣(LeetCode)
题面:

基本分析:子数组是指数组内的索引在父数组中是连续的。
思路:我们可以先定义两个指针,为l,r,分别表示子数组在父数组的范围,我们可以先固定左指针l,然后移动右指针r,左闭右闭,直到找到第一个满足条件的子数组,记录下此时的范围,也就是count=r-l+1,题目既然是让我们找满足条件的长度最小的子数组的长度,那么,正确答案就小于等于count,此时l和r两个指针所围的范围可以看成一个窗口,我们可以从左向右滑动这个窗口,在滑动中判断更新答案,代码和注释如下:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int n = nums.length - 1;// 采取左闭右闭,所以n=nums.length-1
int l = 0;// 左指针
int r = 0;// 右指针
int sum = 0;// 记录窗口内的总值
int count = Integer.MAX_VALUE;// 记录窗口的元素个数
while (r <= n) {
sum += nums[r++];// 右指针向右滑动,更新窗口内的总值
// 进入这个循环就表示至少找到了1个解,当找到了一个解,我们就可以开始滑了
while (sum >= target) {
// 将当前窗口和过去窗口做比较,能进入这个循环就表示r-l(r-l+1,但r在上面已经++了)是一个解,更新解的最小值
count = Math.min(count, r - l);
// 下面这一步很多人最开始会有疑惑,我的理解是:在第一层循环中,右指针是稳定右移的,当我们进入了这个循环,就表示找到了一个解,那么最差的情况,就是第一个找到的解,但是解是小于等于第一个解的,所以我们进入循环就把左边的删1,整体来看就像一个动态变化的窗口在右移
sum -= nums[l++];
}
}
// 如果count==Integer.MAX_VALUE,表示第二层循环没进,也就是无解
return count == Integer.MAX_VALUE ? 0 : count;
}
}
2.最小覆盖子串
题目链接:76. 最小覆盖子串 - 力扣(LeetCode)
题面:
基本分析:虽然是一道困难题,但其实只不过是一道稍微复杂点的滑动窗口,与第一题不同的在于第二层循环的判断条件,在第一题中,根据题意是找sum大于等于target的子数组,进入第二层的判断条件是sum>=target,而这题的判断条件是涵盖t中所有的字符:
什么是涵盖t中的所有字符?:就是对于t中每个字符的数量,某个字符串中的字符数量都大于或等于
分析完后,代码如下:
class Solution {
public String minWindow(String s, String t) {
int n = s.length() - 1;
int m = t.length() - 1;
//如果n<m,不可能涵盖
if (n < m)
return "";
char[] sarr = s.toCharArray();
char[] tarr = t.toCharArray();
int[] arr1 = new int[128];//用来记录字符串s中滑动窗口中的字符数量
int[] arr2 = new int[128];//用来记录字符串t中各字符数量
//记录字符串t中各字符数量
for (int i = 0; i <= m; i++) {
arr2[tarr[i]]++;
}
int ni = Integer.MAX_VALUE;//记录子串的左边界
int nj = Integer.MAX_VALUE;//记录子串的右边界
int i = 0;//左指针
int j = 0;//右指针
int count = Integer.MAX_VALUE;//记录有效子串的长度
while (j <= n) {
arr1[sarr[j]]+=1;
while (isHaveAll(arr1, arr2)) {
if (j - i + 1 < count) {
ni = i;
nj = j;
count = j - i + 1;
}
arr1[sarr[i++]]-=1;
}
j++;
}
//ni==Integer.MAX_VALUE,表示第二层循环没进,无解
if (ni == Integer.MAX_VALUE)
return "";
return s.substring(ni, nj + 1);
}
//此方法用来判断是否满足条件:子串涵盖字符串t
public boolean isHaveAll(int[] arr1, int[] arr2) {
for (int i = 'A'; i <= 'Z'; i++) {
if (arr1[i] < arr2[i]) {
return false;
}
}
for (int i = 'a'; i <= 'z'; i++) {
if (arr1[i] < arr2[i]) {
return false;
}
}
return true;
}
}
三.后言
上面是滑动串口一些最经典的题目,以后碰到其他好题也会更新,希望有所帮助,一同进步,共勉!

753

被折叠的 条评论
为什么被折叠?



