滑动窗口的相关知识
一、什么是滑动窗口?
滑动窗口 = 双指针 + 维护一个连续区间。
通过 left 和 right 两个指针维护一个窗口,避免重复计算。
-
right++:扩大窗口,加入新元素。 -
left++:缩小窗口,移除旧元素。 -
sum:记录窗口内元素之和。
二、什么时候使用?
一般满足以下特点:
-
连续性:题目要求连续子数组、子串。
-
区间性质:需要维护区间的和、长度、字符数量等。
-
单调性:窗口扩大或缩小时,能够判断应该移动哪个指针。
常见题型:长度最小的子数组、最长无重复子串、固定长度子数组最大和。
三、怎么用
主要以第一道题来演示
进窗口 → 判断 → 更新结果 → 出窗口
四、为什么滑动窗口是对的?
核心在于 利用单调性,排除不可能的答案。
以正整数数组、寻找和大于等于 target 的最短子数组为例:
-
sum < target:窗口不满足条件,只能扩大窗口。 -
sum >= target:窗口满足条件,记录长度,再尝试缩小窗口。 -
每次缩小时,已经记录当前答案,因此不会遗漏最优解。
因为数组元素都是正数,扩大窗口只会让和增加,缩小窗口只会让和减少,所以不需要反复回头检查。
五、最后总结
滑动窗口的本质:通过维护连续区间,利用单调性减少重复遍历。
-
暴力枚举:通常 \(O(n^2)\)
-
滑动窗口:典型双指针写法 \(O(n)\)
一,长度最小的子数组

解题思路:
首先让 left 和 right 都指向数组开头,通过 right++ 不断扩大窗口,并累加窗口内的元素。当 sum >= target 时,说明当前窗口满足条件,此时更新最短长度,再通过 left++ 缩小窗口,尝试寻找更短的子数组。直到 sum < target,再继续移动 right。整个过程中两个指针都不需要回退,最终得到最短长度 2

代码演示:
java
public static int minSubArrayLen(int target, int[] nums) {
int left=0,sum=0,len=Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
sum+=nums[right];
while (sum>=target){
//更新len
len=Math.min(len,right-left+1);
sum-=nums[left++];
}
}
return len == Integer.MAX_VALUE ?0 : len;
}
二,无重复字符串的最长字串

解题思路:
首先让 left 和 right 都指向字符串开头,利用哈希表记录窗口内的字符。通过 right++ 不断扩大窗口,如果新字符没有重复,就加入哈希表并更新最长长度;如果出现重复,就通过 left++ 不断移除左侧字符,直到重复消失。因为之前经过的区间已经判断过,所以两个指针都不需要回退,最终得到最长长度 3
代码演示:
java
public static int lengthOfLongestSubstring(String s) {
int left=0,len=0;
// 哈希表记录窗口内的字符
Set<Character> set = new HashSet<>();
for (int right = 0; right < s.length(); right++) {
char ch=s.charAt(right);
while (set.contains(ch)){
//因为哈希表是记录的当前left与right组成的滑块里面的字符,然后判断是否有重复的,所以我们删除是要从当前窗口的开始一直删除到重复的那一个
set.remove(s.charAt(left));
left++;
}
set.add(ch);
len=Math.max(len,right-left+1);
}
return len;
}
