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

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

相关推荐
葳_人生_蕤2 小时前
hot100——动态规划
算法·动态规划
sheeta19982 小时前
LeetCode 每日一题笔记 日期:2025.03.18 题目:3070.元素和小于等于k的子矩阵的数目
笔记·leetcode·矩阵
量化炼金 (CodeAlchemy)2 小时前
【交易策略】基于决策树的机器学习策略:从预测价格到预测市场结构
算法·决策树·机器学习
计算机安禾2 小时前
【C语言程序设计】第33篇:二级指针与指针数组
c语言·开发语言·数据结构·c++·算法·visual studio code·visual studio
雨落在了我的手上2 小时前
C语言之数据结构初见篇(6):单链表的介绍(2)
数据结构
DANGAOGAO2 小时前
数据结构复习(持续更新)
数据结构
落地加湿器2 小时前
Acwing算法课图论与搜索笔记
c++·笔记·算法·图论·dfs·bfs·图搜索算法
cui_ruicheng2 小时前
C++ 数据结构进阶:哈希表原理
数据结构·c++·算法·哈希算法
黎阳之光2 小时前
黎阳之光:AI硬核技术锚定十五五,赋能海空天全域智能感知
大数据·人工智能·算法·安全·数字孪生