Java 滑动窗口算法如果只靠死记硬背,面试时大概率还是会写错
算法面试里最容易让人产生“我以为我懂了”这种错觉的技术,非滑动窗口(Sliding Window)莫属。很多人在刷题的时候,看到题目里提到“连续子数组”、“最长子串”或者“最小覆盖区间”这类关键词,第一反应就是上双指针或者暴力枚举,结果要么是时间复杂度直接 $O(n^2)$ 挂掉,要么是边界条件处理得一塌糊涂。
下一篇
我想搞清楚这种被称为 Swarm-Mother 的架构到底是怎么实现 →
其实滑动窗口的核心逻辑非常统一,它本质上是在维护一个动态的区间。我把常见的几种实战套路拆解了一下,大家可以对照着自己的代码逻辑看看有没有踩坑。
常见的两种核心模式
- 固定窗口大小: 这种最简单,窗口的长度 $K$ 是死板的。你只需要先拉满第一个窗口,然后开始往右移动,每移动一步,就把最左边的元素踢出去,把新进来的元素加进来。
- 变长窗口大小: 这是面试的高频考点。窗口的边界是不确定的,通常需要维护一个
left和right指针。逻辑是:right不断向右扩张以寻找可行解,一旦窗口不再满足题目条件(比如窗口内的字符种类超过了限制),就必须收缩left指针,直到窗口重新变得“合法”。
一个保姆级的通用模板
不管是求最大还是最小,写 Java 时建议直接套这个逻辑框架,能规避掉 80% 的边界溢出问题:
public int slidingWindowTemplate(int[] nums, int target) {
int left = 0, right = 0;
int windowSize = 0;
int ans = 0;
// 这里根据题目要求定义状态,比如当前窗口内的元素和、计数器等
int currentWindowData = 0;
while (right < nums.length) {
// 1. 【进窗】:将 nums[right] 加入窗口,更新窗口状态
right++;
currentWindowData += nums[right - 1];
// 2. 【收缩】:判断当前窗口是否需要收缩(比如窗口太大了,或者不符合条件了)
while (/* 窗口不符合条件的情况 */) {
// 3. 【出窗】:将 nums[left] 移出窗口,更新窗口状态
currentWindowData -= nums[left];
left++;
// 更新窗口大小或状态
}
// 4. 【更新结果】:在窗口合法的情况下,更新最终答案
ans = Math.max(ans, right - left);
}
return ans;
}实战中的几个坑
在做 LeetCode 里的相关题目时,一定要注意 right 指针移动后的状态更新时机。有些题目要求的是“子数组”,有些要求的是“子串”,在处理字符串时,记得要配合 HashMap 或者 int[128] 这种频率数组来记录窗口内的字符分布。
另外,关于 ans 的更新位置,如果是求“最大长度”,通常放在 while 收缩循环之后;如果是求“最小长度”,则要在 while 循环内部更新。这种细节如果不搞清楚,代码写出来逻辑就是反的。
免费 AI 工具箱 · 全部完全免费
