9.LeetCode 209. 长度最小的子数组 | 滑动窗口专题详解

目录

[1. 题目解析](#1. 题目解析)

[示例 1:](#示例 1:)

[示例 2:](#示例 2:)

[2. 算法原理](#2. 算法原理)

[解法一:暴力枚举所有子数组的和 ------ O(n²)](#解法一:暴力枚举所有子数组的和 —— O(n²))

[解法二:利用单调性,使用"同向双指针"来优化 ------ O(n)](#解法二:利用单调性,使用“同向双指针”来优化 —— O(n))

[✅ 怎么用?](#✅ 怎么用?)

图解过程:

正确性?

时间复杂度

[3. 编写代码](#3. 编写代码)

[OJ链接:​ https://leetcode.cn/problems/minimum-size-subarray-sum/description/](#OJ链接: https://leetcode.cn/problems/minimum-size-subarray-sum/description/)


1. 题目解析

本题来自 LeetCode 第 209 题:长度最小的子数组

**题目描述:**​

给定一个含有 n个正整数的数组和一个正整数 target

找出该数组中满足其和 ≥ target的长度最小的 连续子数组[nums[l], nums[l+1], ..., nums[r-1], nums[r]],并返回其长度。如果不存在符合条件的子数组,返回 0

示例 1:

java 复制代码
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下长度最小的子数组。

示例 2:

java 复制代码
输入:target = 4, nums = [1,4,4]
输出:1

📌 关键点:

  • 子数组必须是连续的

  • 要求和 ≥ target

  • 返回的是最小长度,不是子数组本身

  • 若不存在,返回 0


2. 算法原理

解法一:暴力枚举所有子数组的和 ------ O(n²)

通过双重循环枚举所有子数组,计算和并比较,时间复杂度为 O(n²),在数据规模大时会超时。


解法二:利用单调性,使用"同向双指针"来优化 ------ O(n)

这是本题的核心解法:滑动窗口(Sliding Window)

✅ 怎么用?

我们用两个指针 leftright构建一个窗口 ,窗口内的元素和记为 sum,窗口长度记为 len

步骤如下:

  1. 初始化:left = 0, right = 0

  2. 进窗口 ​ → right向右移动,将 nums[right]加入 sum

  3. 判断 ​ → 如果 sum >= target,说明当前窗口满足条件,尝试缩小窗口

    • 更新最小长度:len = min(len, right - left + 1)

    • 出窗口 ​ → left向右移动,sum -= nums[left++]

  4. 重复步骤 2~3,直到 right遍历完整个数组

图解过程:

target = 7, nums = [2,3,1,2,4,3]为例:

  • 初始:left=0, right=0, sum=0, len=+∞

  • right=0→ 进窗口:sum=2→ 不满足

  • right=1→ 进窗口:sum=5→ 不满足

  • right=2→ 进窗口:sum=6→ 不满足

  • right=3→ 进窗口:sum=8→ 满足!→ 更新 len=4,出窗口:sum=6, left=1

  • right=4→ 进窗口:sum=10→ 满足!→ 更新 len=4(当前窗口 3,1,2,4),出窗口:sum=8, left=2

  • right=5→ 进窗口:sum=11→ 满足!→ 更新 len=31,2,4),出窗口:sum=7, left=3

  • right=5→ 再次判断:sum=7 >=7→ 更新 len=22,4),出窗口:sum=3, left=4

  • 循环结束

✅ 最终最小长度为 2


正确性?

利用单调性,规避了很多没有必要的枚举行为

因为数组元素都是正整数 ,所以当 sum >= target时,我们移动 left指针一定能缩小窗口,且不会错过更优解。这是滑动窗口能成立的核心前提。


时间复杂度

  • right指针遍历数组一次 → O(n)

  • left指针也最多移动 n 次 → O(n)

  • 总体:O(n)

✅ 从 n+n → 2n → O(n),线性时间复杂度,非常高效!


3. 编写代码

以下是 Java 实现代码

java 复制代码
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length, sum = 0, len = Integer.MAX_VALUE;
        for (int left = 0, right = 0; right < n; right++) {
            sum += nums[right]; // 进窗口
            while (sum >= target) { // 判断
                len = Math.min(len, right - left + 1); // 更新结果
                sum -= nums[left++]; // 出窗口
            }
        }
        return len == Integer.MAX_VALUE ? 0 : len;
    }
}

可直接复制运行。

欢迎在评论区留言交流,我们一起把滑动窗口吃透!


OJ链接:https://leetcode.cn/problems/minimum-size-subarray-sum/description/

祝你刷题顺利,早日拿Offer!++点个关注++

相关推荐
菜菜的顾清寒5 小时前
力扣hot100(37)栈-有效的括号
java·开发语言
孟林洁5 小时前
Java转AI应用开发速成(3)—— 第一个 SpringAI 聊天应用
java·spring boot·后端·ai·机器人
Simon523145 小时前
Spring AOP 五大通知类型
java·前端·spring
水蓝烟雨6 小时前
0135. 分发糖果
算法·leetcode
IronMurphy6 小时前
【算法五十二】5. 最长回文子串
算法
早睡身体真不戳6 小时前
【无标题】
java·服务器·windows
布吉岛的石头6 小时前
Java 程序员第 38 阶段:Embedding 向量缓存实战,减少重复向量化计算开销
java·缓存·embedding
Circ.6 小时前
Java 远程调用 NX 11 完整实战:参数读取、修改、STP 文件导出(附环境配置 + 源码)
java·开发语言·nx11
Lewiis6 小时前
白话选择排序
数据结构·算法·排序算法