算法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. 滑动窗口(双指针)法(最优解):

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

    • 步骤:

      1. 初始化 :left = 0,right = 0,sum = 0,minLen = 无穷大(如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. 初始化 :left和 right都从 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。

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

相关推荐
垆边人似月.4 分钟前
华为题:无重复字符的最长子串变种
算法
糖果豆豆10 分钟前
灾难性遗忘不是"新旧打架"——旧知识记不住,是因为它没长成"环"
算法
垆边人似月.12 分钟前
华为题:任务调度
数据结构·c++·算法
垆边人似月.13 分钟前
华为题:编辑距离
算法·华为
会灭火的程序员14 分钟前
大模型部署硬件资源计算指南:从显存估算到显卡选型
人工智能·算法
Logic10119 分钟前
C语言/数据结构字符串题解:解压缩“字符+次数“格式——多位数字处理与字符串还原
c语言·数据结构·字符串·模拟·时间复杂度·空间复杂度·算法题
信奥卷王21 分钟前
[GESP202506 六级] 最大因数(含视频)
数据结构·算法
局部有解28 分钟前
Leetcode - 42 接雨水(一维)
数据结构·c++·算法·leetcode
垆边人似月.33 分钟前
华为题:矩阵中的最长递增路径
算法·深度优先
小诗懂技术36 分钟前
linux驱动中断,相关中断的方式与适用场景
linux·arm开发·驱动开发·算法