算法9,滑动窗口,长度最小的子数组

复制代码
public int minSubArrayLen(int target, int[] nums) {
        int left=0;
        int right=0;
        int sum=nums[left];
        if(sum>=target){
            return 1;
        }
        else right++;
        sum+=nums[right];
        int len=right-left+1;
        while(sum>=target){
            sum-=nums[left];
            left++;
            if(len<=right-left+1){
                len=right-left+1;
            }
            while (sum<target){
                right++;
                sum+=nums[right];
                if(len<=right-left+1){
                    len=right-left+1;
                }
                
            }
        }
        return len;
    }

其核心内容是 "长度最小的子数组"问题​ 的算法笔记。以下从题目分析、算法分析和代码编写三个方面进行总结:


题目分析

  • 问题 :给定一个含有 n正整数 的数组和一个正整数 target,找出该数组中满足其和 ≥ target ​ 的长度最小的连续子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

  • 输入 :一个正整数数组 nums,一个正整数 target

  • 输出:最小子数组的长度。

  • 示例 :笔记中以数组 [2,3,1,2,4,3]target = 7为例。符合条件的子数组有 [4,3][2,4,3],最小长度为 2。

算法分析

笔记中对比了两种解法:

  1. 暴力枚举法

    • 思路 :枚举所有可能的子数组(通过双重循环确定左右边界),计算每个子数组的和,判断是否 ≥ target并记录最小长度。

    • 缺点:时间复杂度为 O(n²)(若每次求和都重新计算,则为 O(n³)),效率低下。

  2. 滑动窗口(双指针)法(最优解)

    • 核心思想 :利用数组元素均为正数的单调性 ,使用两个同向移动的指针(leftright)构成一个窗口。通过动态调整窗口大小,在 O(n) 时间内找到最小窗口。

    • 步骤

      1. 初始化left = 0right = 0sum = 0minLen = 无穷大(如INT_MAX)

      2. 进窗口 :将 nums[right]加到 sum中,然后 right右移。

      3. 判断 :当 sum >= target时,说明当前窗口满足条件。

        • 更新结果 :计算当前窗口长度 right - left,并更新 minLen

        • 出窗口 :从 sum中减去 nums[left],然后 left右移,以尝试缩小窗口,寻找更小的满足条件的窗口。

      4. 重复步骤 2 和 3,直到 right到达数组末尾。

    • 优点:每个元素最多被访问两次(进窗口和出窗口各一次),时间复杂度为 O(n),空间复杂度为 O(1)。

代码编写

以下是修正和完善图片中代码逻辑后的 Java 实现:

复制代码
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        int left = 0;      // 窗口左边界
        int right = 0;     // 窗口右边界
        int sum = 0;       // 窗口内元素的和
        int minLen = Integer.MAX_VALUE; // 最小长度,初始化为最大值

        while (right < n) {
            // 1. 进窗口:右指针向右移动,扩大窗口
            sum += nums[right];
            
            // 2. 判断:当窗口内元素和满足条件时,尝试收缩窗口以找到更小的窗口
            while (sum >= target) {
                // 3. 更新结果:计算当前窗口长度并更新最小值
                int currentLen = right - left + 1;
                minLen = Math.min(minLen, currentLen);
                
                // 4. 出窗口:左指针向右移动,缩小窗口
                sum -= nums[left];
                left++;
            }
            
            // 继续移动右指针,扩大窗口
            right++;
        }
        
        // 如果 minLen 没有被更新过,说明没有符合条件的子数组,返回 0
        return (minLen == Integer.MAX_VALUE) ? 0 : minLen;
    }
}

代码说明

  1. 初始化leftright都从 0 开始,sum初始为 0,minLen初始为 Integer.MAX_VALUE

  2. 主循环while (right < n)控制右指针遍历整个数组。

  3. 进窗口 :每次循环先将当前 right指向的元素加入 sum

  4. 内层循环 :当 sum >= target时,说明当前窗口满足条件。此时:

    • 计算当前窗口长度 right - left + 1,并更新 minLen

    • 然后从 sum中减去 nums[left],并将 left右移一位,以尝试寻找更小的满足条件的窗口。

    • 这个内层循环会持续到 sum < target,确保我们找到了以当前 right为右边界的最小满足条件的窗口。

  5. 移动右指针 :内层循环结束后,right右移,继续探索下一个元素。

  6. 返回值 :如果 minLen从未被更新,则返回 0;否则返回 minLen

此解法是解决"长度最小的子数组"问题的标准滑动窗口方法,高效且易于理解。

相关推荐
吃好睡好便好5 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
仰泳之鹅6 小时前
【C语言】自定义数据类型2——联合体与枚举
c语言·开发语言·算法
x_yeyue8 小时前
三角形数
笔记·算法·数论·组合数学
Mr. zhihao9 小时前
深入解析redis基本数据结构
数据结构·数据库·redis
念何架构之路9 小时前
Go语言加密算法
数据结构·算法·哈希算法
AI科技星9 小时前
《数学公理体系·第三部·数术几何》(2026 年版)
c语言·开发语言·线性代数·算法·矩阵·量子计算·agi
失去的青春---夕阳下的奔跑9 小时前
560. 和为 K 的子数组
数据结构·算法·leetcode
黎阳之光10 小时前
黎阳之光:以视频孪生重构智慧医院信息化,打造高标项目核心竞争力
大数据·人工智能·物联网·算法·数字孪生
丷丩10 小时前
三级缓存下MVT地图瓦片服务性能优化策略
算法·缓存·性能优化·gis·geoai-up
m0_6294947310 小时前
LeetCode 热题 100-----25.回文链表
数据结构·算法·leetcode·链表