代码随想录-数组04-209 长度最小的子数组-java

目录

描述

思路 

代码


  •   描述


  • 思路 

        B站大佬讲解

  • 暴力破解

       一个for循环,固定起始位置,一个for循环寻找符合条件的子数组,并记录长度

        例如数组为a b c d e f 

        子数组 a,a+b,a+b+c>=target; break; length = 3

        子数组 b,b+c,b+c+d,b+c+d+e>=target; break; 4>3  length=3

        ....     

  • 滑动窗口法

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

        滑动窗口内是什么:符合条件的子数组 

        窗口的起始位置如何移动:窗口值>=s,起始位置就要向前移动了(也就是该缩小了)。

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

例如a+b+c<target,a+b+c+d>=target

暴力从b重新累加,但是可以进行优化。
b+c一定小于target ,所以我们直接看b+c+d是否>=target,也就是从上一个符合条件的子数组减去它的初始元素,相当于滑动窗口的起始位置向前移动一位。

那么应该如何实现呢?

for循环里面是终止位置的索引 j

起始索引 为i=0; sum=0;

sum = sum+nums[j]

while(sum>=target),记录子序列长度并更新最小子序列长度,sum-nums[i];i++;//找到最短子数组

while 和 if 的区别

  1. while 的作用

    • 当 sum >= target 时,while 会不断收缩左边界 i,直到 sum < target

    • 这样可以确保找到以当前 j 为右边界的最短子数组。

  2. if 的作用

    • 当 sum >= target 时,if 只会执行一次,收缩左边界 i 一次。

    • 这样无法确保找到以当前 j 为右边界的最短子数组。

为什么不能将 while 改为 if

如果将 while 改为 if,滑动窗口的逻辑会失效,具体表现为:

  1. 无法找到最短子数组

    • if 只会尝试收缩一次左边界,可能无法将窗口缩小到最小。

    • 例如,如果窗口内的和远大于 targetif 只会减去一个元素,而 while 会不断减去元素,直到窗口内的和小于 target

  2. 可能漏掉更短的子数组

    • if 只收缩一次,可能导致窗口仍然较大,从而漏掉更短的满足条件的子数组。

  • 代码

        暴力破解:

//暴力解 超时
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int min = Integer.MAX_VALUE;
        int length=0;
        for(int i=0;i<nums.length;i++){
            int sum = nums[i];
            if(sum>=target){
                length = 1;
            }
            else{
                for(int j=i+1;j<nums.length;j++){
                    sum += nums[j];
                    if(sum>=target){
                        length = j-i+1;
                        break;
                    }
                }
            }
            if(length<min){
                min = length;
            }
        }
        return min==Integer.MAX_VALUE?0:min;
    }
}

          滑动窗口:

//滑动窗口
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int i=0;
        int min=Integer.MAX_VALUE;
        int length = 0;
        int sum = 0;
        for(int j=0;j<nums.length;j++){
            sum+=nums[j];
            while(sum>=target){
                length = j-i+1;
                if(length<min){
                    min = length;
                }
                sum = sum-nums[i];
                i++;
            }
        }
        return min==Integer.MAX_VALUE?0:min;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值