LeetCode 209.长度最小子数组

题目描述:

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 子数组

[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

算法思路:

        第一种暴力法,我认为也是双指针法(会超时)

        「从前往后」枚举数组中的任意⼀个元素,把它当成起始位置。然后从这个「起始位置」开始,然 后寻找⼀段最短的区间,使得这段区间的和「⼤于等于」⽬标值。 将所有元素作为起始位置所得的结果中,找到「最⼩值」即可。

算法代码:

class Solution {
       public int minSubArrayLen(int target, int[] nums) {
        int n = nums.length;
        int ret = Integer.MAX_VALUE; //ret初始化记录赋值最大值,方便最小的值都可以替换
        for (int start = 0; start < n; start++) {  //开始指针
            int sum = 0;  //记录本次指针总和sum的值
            for (int end = start; end < n; end++) {  //结束指针
                sum += nums[end];  //每次都添加end指针的值
                if (sum >= target) {
                    ret = Math.min(ret, end - start + 1); //每次结束判断最小值是本次吗
                    break;
                }
            }
        }
        return ret == Integer.MAX_VALUE ? 0 : ret;  //如果结束的值还是和初始值一样就返回0.否则返回ret
    }
}

第二种: 滑动窗口 O(N)

算法思路:

        因为是连续的区间,可以使用滑动窗口来解决。

        当窗口中的值满足判断条件,记录此时的值,然后和最小值比。具体思路当让滑动窗⼝满⾜:从 left 位置开始,窗⼝内所有元素的和⼩于 target (那么当窗⼝内元素之和 第⼀次⼤于等于⽬标值的时候,就是 left位置开始,满⾜条件的最⼩⻓度)。然后left可以右移动一位。

        具体:当我们找到了一个满足条件的最小值,我们需要找到其他值,其实可以大胆的去掉现在的left,这样也可以避免大量的重复的计算。比如第一个left1到right1是满足条件的,更新结果以后left1右移一位,变成left2.此时有两种情况

第一种:left2-right1不满足

        不满足的原因是left2小于left1,那么right1就要一直右移直到满足条件

第二种:left2-right1满足

        满足的原因是left2大于left1,此时right1不用移动,更新此时的最小值,然后比较。 然后left2右移动一位,变成left3。

        此时又有两种情况    

                第一种:left3-right1不满足

                        不满足的原因是left3小于left2,那么right1就要一直右移直到满足条件。

                第二种:left3-right1满足

                               满足的原因是left3大于left2,此时right1不用移动,更新此时的最小值,然后比较。 然后left2右移动一位,变成left3。此时我们可以看到我们的最小值刚刚开始的[left1...right1],变成了[left3...right1],最小值和原来的比较小了2个。

算法代码:

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int n =nums.length,minSize = Integer.MAX_VALUE,sum = 0;//初始化值
        for (int left = 0,right = 0; right < n; right++) {
             sum += nums[right];//进窗口,不断的添加右指针
             while (sum >= target){//判断,直到sum >= target的时候
                 minSize = Math.min(minSize,right-left+1); //更新结果
                 sum -= nums[left]; //出窗口
                 left++;//左指针右移动一位
             }
        }
        return minSize == Integer.MAX_VALUE ? 0:minSize; //如果结束的值还是和初始值一样就返回0.否则返回ret

    }
}

结果展示:

       ​​​​​​​

        

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值