Java 滑动窗口算法如果只靠死记硬背,面试时大概率还是会写错

PromptCube 初级 1小时前 199 浏览 3 点赞 约 2 分钟

算法面试里最容易让人产生“我以为我懂了”这种错觉的技术,非滑动窗口(Sliding Window)莫属。很多人在刷题的时候,看到题目里提到“连续子数组”、“最长子串”或者“最小覆盖区间”这类关键词,第一反应就是上双指针或者暴力枚举,结果要么是时间复杂度直接 $O(n^2)$ 挂掉,要么是边界条件处理得一塌糊涂。

其实滑动窗口的核心逻辑非常统一,它本质上是在维护一个动态的区间。我把常见的几种实战套路拆解了一下,大家可以对照着自己的代码逻辑看看有没有踩坑。

常见的两种核心模式

  • 固定窗口大小: 这种最简单,窗口的长度 $K$ 是死板的。你只需要先拉满第一个窗口,然后开始往右移动,每移动一步,就把最左边的元素踢出去,把新进来的元素加进来。
  • 变长窗口大小: 这是面试的高频考点。窗口的边界是不确定的,通常需要维护一个 leftright 指针。逻辑是:right 不断向右扩张以寻找可行解,一旦窗口不再满足题目条件(比如窗口内的字符种类超过了限制),就必须收缩 left 指针,直到窗口重新变得“合法”。
Java 滑动窗口算法如果只靠死记硬背,面试时大概率还是会写错

一个保姆级的通用模板

不管是求最大还是最小,写 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 循环内部更新。这种细节如果不搞清楚,代码写出来逻辑就是反的。

JavaLeetCode

全部回复 (3)

阿海爱学习 高级 1小时前
确实,边界问题最坑。话说窗口收缩时,那个while循环的条件该怎么定才稳?
0 回复
T
Tom 中级 1小时前
上次面大厂就栽在这,窗口右边界加完之后,忘了判断左边界是否越界,结果直接报错。
0 回复
数据分析师大山 中级 1小时前
还得看哈希表怎么存,我上次就是因为窗口收缩时没及时更新频率,结果算出来的全是错的。
0 回复

发表回复

支持 Markdown 格式