LeetCode 209 · 滑动窗口经典题型

在数组中找大于等于目标值的最小子数组的长度

LeetCode 209 · 滑动窗口经典题型

题目描述

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

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

解题思路

核心思路:用滑动窗口找到以每个元素开头的最小子数组,不断更新最小长度

第一步:初始化最小长度

javascript 复制代码
let min = nums.length + 1;

为什么让 min = nums.length + 1 而不是 nums.length

因为题目要求:不存在符合条件的子数组时,返回 0

假设令 min = nums.length,来看一个问题场景:

步骤 操作 sum min
1 遍历完整个数组 sum < target nums.length(未更新)

遍历结束后 sum 仍然小于 target,说明不存在符合条件的子数组,应该返回 0

但此时 min = nums.length,如果直接返回 min,就返回了错误的值。

解决方案:令 min = nums.length + 1,用它作为"未找到"的标志。

最终返回时:

javascript 复制代码
return min === nums.length + 1 ? 0 : min;

这样只要 min 没被更新过(还是初始值),就说明没找到,返回 0

第二步:滑动窗口找最小长度

用两个指针 leftright 维护一个窗口:

  • left:确定子数组的开头
  • right:确定子数组的结尾,不断右移使 sum ≥ target
javascript 复制代码
let left = 0;
let right = 0;
let sum = 0;
let min = nums.length + 1;

for (; right < nums.length; right++) {
    sum += nums[right];

    while (sum >= target) {
        min = Math.min(right - left + 1, min);
        sum -= nums[left];
        left++;
    }
}

return min === nums.length + 1 ? 0 : min;

关键问题:为什么用 while 而不是 if

javascript 复制代码
while (sum >= target) {  // ← 为什么是 while,不是 if?
    min = Math.min(right - left + 1, min);
    sum -= nums[left];
    left++;
}

因为当当前子数组的和 sum ≥ target 时,就可以开始尝试缩短子数组,看看去掉左边元素后是否仍然满足条件。

如果用 if:只会缩短一次就跳出,可能错过更短的合法子数组。

while:会一直缩短,直到 sum < target,确保找到的是以当前 right 结尾的最短合法子数组。

图解示例

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

步骤 窗口 sum 操作
1 [2] 2 right 右移
2 [2, 3] 5 right 右移
3 [2, 3, 1] 6 right 右移
4 [2, 3, 1, 2] 8 ≥ 7 min = 4,left 右移 → sum = 6 < 7
5 [3, 1, 2, 4] 10 ≥ 7 min = 4,left 右移 → [1, 2, 4] sum = 7 ≥ 7,min = 3 ,left 右移 → [2, 4] sum = 6 < 7
6 [2, 4, 3] 9 ≥ 7 min = 3,left 右移 → [4, 3] sum = 7 ≥ 7,min = 2 ,left 右移 → [3] sum = 3 < 7

最终结果:min = 2(子数组 [4, 3]

注意步骤 5while 让窗口从 [3, 1, 2, 4] 逐步缩短到 [2, 4],中间经过 [1, 2, 4](sum = 7 ≥ 7),所以 min 能被更新为 3。如果用 if 就会错过这一步。

完整代码

javascript 复制代码
var minSubArrayLen = function (target, nums) {
    let left = 0;
    let sum = 0;
    let min = nums.length + 1;

    for (let right = 0; right < nums.length; right++) {
        sum += nums[right];

        while (sum >= target) {
            min = Math.min(right - left + 1, min);
            sum -= nums[left];
            left++;
        }
    }

    return min === nums.length + 1 ? 0 : min;
};

复杂度分析

复杂度 说明
时间复杂度 O(n) 每个元素最多被 leftright 各访问一次
空间复杂度 O(1) 只用了几个变量

总结

要点 说明
min 初始化为 nums.length + 1 作为"未找到"的标志,最终通过三元表达式返回 0 或 min
while 而非 if 确保找到以当前 right 结尾的最短合法子数组
窗口缩小时更新 min 每次 left 右移前,用当前窗口长度尝试更新最小值
相关推荐
hetao173383716 分钟前
2026-09-01~09-04 hetao1733837 的刷题记录
c++·算法
Evand J34 分钟前
【MATLAB例程,图像滤波5】 反谐波均值滑动窗口滤波(CHMF)图像降噪与质量评价,附代码下载链接
图像处理·算法·计算机视觉·matlab·均值算法·滑动窗口滤波·均值滑动
血小板要健康1 小时前
链表 阶段算法总结
java·数据结构·笔记·算法·leetcode·链表
a187927218311 小时前
【算法】回溯算法(三):三记重锤与 N 皇后——记忆化、状态设计与三层漏斗
算法·leetcode·go·剪枝·回溯·n皇后·算法讲解
HugoStudio_SWAN3 小时前
洛谷 P1420 / P1179 / B4262 最长连号、数字统计与词频统计——统计的三种面孔
c++·学习·程序人生·算法
青 春 记 忆4 小时前
LeetCode 350. 两个数组的交集 II|Python 解法详解
python·算法·leetcode
阳明山水4 小时前
销量预测2025—2026:从模型竞赛到系统融合的范式转型
人工智能·深度学习·算法·机器学习·架构
桐盛科技5 小时前
拒绝“漂绿”风险:基于边缘计算的碳排放数据清洗算法与实时校验逻辑
人工智能·算法·边缘计算
Tongzhi20265 小时前
通芝科技考勤软件三大发展趋势:AI大模型、无感识别与数据底座
大数据·科技·算法·爬山算法
eBest数字化转型方案5 小时前
Route Optimization for FMCG:多目标排线算法的工程实现
大数据·人工智能·算法