算法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

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

相关推荐
To_OC6 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
2401_841495647 小时前
【操作系统】进程同步与互斥实验报告
c++·算法·操作系统·进程·并发·同步·互斥
爱刷碗的苏泓舒11 小时前
PPP-AR 中的参考星选取:数学原理、评价指标与切换处理
算法·gnss·模糊度固定·ppp-ar·星间单差·参考星·卫星端偏差
烬羽14 小时前
递归老写崩?一个"退回"公式,把回溯题变成填空题
javascript·深度学习·算法
闪电悠米14 小时前
力扣hot100-41.缺失的第一个正数-原地哈希详解
数据结构·算法·哈希算法
WL学习笔记14 小时前
堆(数据结构)
数据结构·
星空露珠14 小时前
28种颜色对应名称,
开发语言·数据库·算法·游戏·lua
QXWZ_IA16 小时前
桥梁数字孪生怎么落地?
人工智能·科技·算法·智能硬件·政务
Kel16 小时前
输出层与反分词(Output Layer & Detokenization)
人工智能·算法·架构