当前位置: 首页 > news >正文

代码随想录 第一章 数组 209.长度最小的子数组

代码随想录 第一章 数组 209.长度最小的子数组

题目: 209.长度最小的子数组

  • 题目描述:

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

    找出该数组中满足其总和大于等于target​ 的长度最小的 子数组 [numsₗ, numsₗ₊₁, ..., numsᵣ₋₁, numsᵣ]​ ,并返回其长度 如果不存在符合条件的子数组,返回 0​ 。

一、思想

滑动窗口的核心思想是就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ target​ 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于等于target​了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

解题的关键在于窗口的起始位置如何移动。

滑动窗口算法详解(示例:nums=[2,3,1,2,4,3]​, target=7​)

右指针当前元素窗口范围累计和是否触发收缩操作记录最小长度左指针位置变化轨迹
02[0,0]2右移 →0 → 0
13[0,1]5右移 →0 → 0
21[0,2]6右移 →0 → 0
32[0,3]8① 长度=4 → subLength=4
sum-=2​ → sum=6
③ 左指针移动 →left=1
40 → 1
44[1,4]10① 长度=4 → 不更新
sum-=3 ​→ sum=7
③ 左移 → left=2
再次检测 → 长度=3 → subLength=3
sum-=1​ → sum=6
⑥ 左指针移动→ left=3
31 → 3
53[3,5]9① 长度=3 → 不更新
sum-=2​ → sum=7
③ 左移 → left=4
再次检测 → 长度=2 → subLength=2
sum-=4​ → sum=3
⑥ 左指针移动→ left=5
23 → 5

二、代码

/**
 * 类Solution:解决问题
 */
class Solution
{
public:
    /**
     * 函数minSubArrayLen:寻找最短的子数组,其和至少为target
     * @param target 目标和
     * @param nums 整数数组
     * @return 返回最短子数组的长度,如果不存在满足条件的子数组,返回0
     */
    int minSubArrayLen(int target, vector<int> &nums)
    {
        // 初始化结果为最大整数
        int result = INT_MAX;
        // 初始化当前和为0
        int sum = 0;
        // 初始化子数组的起始位置为0
        int i = 0;
        // 初始化子数组的长度为0
        int subLength = 0;
        // 遍历数组
        for (int j = 0; j < nums.size(); j++)
        {
            // 更新当前和
            sum += nums[j];
            // 当当前和大于等于目标和时
            while (sum >= target)
            {
                // 更新子数组的长度
                subLength = j - i + 1;
                // 更新结果为当前结果和子数组长度的最小值
                result = result < subLength ? result : subLength;
                // 更新当前和
                sum -= nums[i++];
            }
        }
        // 如果结果仍为最大整数,返回0,否则返回结果
        return result == INT_MAX ? 0 : result;
    }
};

三、解析

1. 算法工作原理分解

1.1 初始化阶段

  • 核心变量定义

    int result = INT_MAX;  // 最小长度记录器(初始设为极大值)
    int sum = 0;           // 窗口和累计器
    int i = 0;             // 左指针(窗口起始位置)
    
  • 初始状态

    • 窗口范围:[0, 0)​(空窗口)
    • 示例:nums=[2,3,1,2,4,3]​ 初始时 sum=0

1.2 右指针主导窗口扩展

  • 遍历机制

    for(int j=0; j<nums.size(); j++) {  // j为右指针
        sum += nums[j];                 // 动态扩展窗口右边界
    
  • 操作特点

    • 右指针 j​ 单向前进(从0到n-1)
    • 每次扩展必然添加新元素到窗口
    • 示例:当 j=3​ 时,窗口扩展为 [2,3,1,2]

1.3 收缩条件检测

  • 触发条件

    while(sum >= target) {  // 必须用while循环
    
  • 检测逻辑

    • 当窗口和 sum​ ≥ target​ 时进入收缩阶段
    • 示例:j=3​ 时 sum=8 ≥7​ 触发收缩

1.4 窗口收缩与最小长度更新

  • 收缩操作流程

    1. 计算当前窗口长度

      subLength = j - i + 1;  // 闭区间长度计算
      
    2. 更新最小长度

      result = min(result, subLength);  // 取历史最小值
      
    3. 左指针右移

      sum -= nums[i++];  // 先减元素值,再移动左指针
      
  • 操作示例

    • 当窗口为 [2,3,1,2]​ 时:

      • 计算长度 4​ → 更新 result=4
      • 收缩后窗口变为 [3,1,2]​,sum=6

1.5 连续收缩机制

  • 多轮收缩场景

    while(sum >= target) {  // 可能执行多次收缩
        // 上述收缩操作
    }
    
  • 必要性

    • 确保找到以当前右指针为终点的最小窗口

    • 示例:当 j=4​ 时窗口 [1,4]​ 需连续收缩两次

      • 第一轮收缩:窗口 [2,4]​,sum=7
      • 第二轮收缩:窗口 [3,4]​,sum=6​(退出循环)

1.6 最终结果处理

  • 无效结果判断

    return (result == INT_MAX) ? 0 : result;
    
  • 逻辑意义

    • 若从未找到有效窗口(result​未更新),返回0
    • 示例最终结果:result=2​(窗口 [4,3]​)
2. 关键点说明
操作阶段时间复杂度保障机制示例中的操作表现
右指针扩展单层for​循环 → O(n)右指针完整遍历数组(6次移动)
左指针收缩每个元素最多被左指针访问一次 → O(n)左指针共移动4次(0→1→2→3→5)
窗口计算即时更新result​ → O(1) 操作3次有效更新(4→3→2)
循环检测while​确保完全收缩 → 无遗漏步骤5中触发两次连续收缩

四、复杂度分析

  • 时间复杂度O(n)
    滑动窗口的 左指针 left和右指针 right均单向移动,每个元素最多被访问两次(右指针扩展时访问一次,左指针收缩时访问一次)。对于长度为 n​ 的数组,总操作次数为 2n​ 次,最终时间复杂度为线性级别。
  • 空间复杂度O(1)
    仅使用固定数量的额外空间(sum​、left​、result​ 等整型变量),空间消耗与输入规模 n​ 无关。

相关文章:

  • Postgresql的三种备份方式_postgresql备份
  • 如何在在 CentOS 中安装 OLama
  • 企业实战 - 深入解析Python爬虫中的JS逆向技术
  • 【机器学习】线性回归 多项式线性回归
  • web信息泄露 ctfshow-web入门web1-web10
  • mysql 学习15 SQL优化,插入数据优化,主键优化,order by优化,group by 优化,limit 优化,count 优化,update 优化
  • CentOS上远程连接SSH常用操作命令整理
  • 字符串哈希动态规划_6
  • 二.数据治理流程架构
  • 《程序人生》工作2年感悟
  • Leetcode 424-替换后的最长重复字符
  • 复用输出模式的使用场景
  • [STM32 - 野火] - - - 固件库学习笔记 - - - 十五.设置FLASH的读写保护及解除
  • Vue 3最新组件解析与实践指南:提升开发效率的利器
  • 《Zookeeper 分布式过程协同技术详解》读书笔记-2
  • Android 14输入系统架构分析:图解源码从驱动层到应用层的完整传递链路
  • 数据仓库、数据湖和数据湖仓
  • Postgresql在线重建索引REINDEX INDEX CONCURRENTLY出现后缀带_ccnew和_ccold关键字且状态是invaild的索引
  • 一天急速通关Linux
  • 华为交换机trunk简介配置
  • 工程院院士、武汉纺织大学校长徐卫林拟任湖北省属本科高校党委书记
  • 马上评|去年维修竣工的鼓楼,今年就“瀑布式落瓦”
  • 减重人生|吃得越少越好?比体重秤上的数字,更有意义的是什么?
  • 上海中心城区首条“定制化低空观光航线”启航,可提前一天提需求
  • 广东茂名高州市山体滑坡已致3死1失联,搜救仍在继续
  • 梅花奖在上海|秦海璐:演了15年《四世同堂》,想演一辈子