长度最小的子数组 - 使用“滑动窗口”

                                     🍉🍉  今天的博客又来了又来了🍉🍉

1.题目解析

题目是:

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

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

解析:题目的意思很好理解就是数组中连续的数的和 == target,连续个数最短的集合,很容易理解。

2.解法原理

看到一道题我们大多数人都是先选择使用暴力解法,这是最基本的解法,但是大多数情况只适用简单题,大多数情况 ,暴力解法的复杂度比较高,运行时间过长会导致代码跑超时。

所以这道题,使用暴力枚举的方法很简单,两个for循环可以直接解决:

用图和伪代码来说就是

第一层循环:

第二层循环:

public int minSubArrayLen(int target, int[] nums) {
        int len = Integer.MAX_VALUE;//一定要将len的值设置为最大值,因为0和任何数相比都会比他小,题目要求数组都属正数
        for(int left = 0;left < nums.length;left++){
//定义第一层循环
            int sum = 0;
            for(int right = left;right < nums.length;right++){
定义第二层循环
                 sum +=nums[right];
                 if(sum >= target){
                  //判断值是否大于或者等于target
                    len = Math.min(len,right-left+1);//取最小长度
                    break;//退出第二层循环
}

                
}
return len == Integer.MAX_VALUE ? 0 : len;
}
}

优化:

我们想想在进入第二层循环,我们有没有必要将right退回至left处,重新计算sum的值,我们已经计算过一次sum,如果我们将left向前推进一步前,将left所在的位置的值在sum减去,重新判断sum的值是否 > target.是不是就不用将right再返回来,浪费时间复杂度,这样我们只需要遍历一次数组即可解决问题。

红字部分我们需要注意,这里会出现两种种情况 如果新的 sum >= target 即重新计算len,sum<taget,只需要让right++即可。

说到这里终于到我们的重头戏了

滑动窗口:基于单调性,使用  "同向双指针",对窗口进行调整。

Ps:没看错 还是老朋友双指针

一般分为三个步骤:

1.指针1:left = 0,right = 0;

调整窗口

2.进窗口:对于本题来说移动 right 

3.判断 :对于本题来说是 sum >= target

更新结果:本题是 对最数组最小长度len进行更新 

出窗口 :调整 left.

基于对上面的解释我们可以知道,进入窗口开始我们要一直对left right的位置进行调整,所以需要一个循环,前面咱也说了在判断阶段,我们不清楚更新后的sum有两种情况,如果sum > target,我们要继续对len进行更新,继续对sum的调整,所以这里需要一个循环。

3. 代码演示

    public int minSubArrayLen(int target, int[] nums) {
//定义两个指针,并且设置len为最大值,以免为0冲突。
        int left = 0,right = 0,n = nums.length,len = Integer.MAX_VALUE,sum = 0;
        for(;right < n;right++){
            sum += nums[right];//进入窗口
            while(sum >= target){//判断
                len = Math.min(len,right-left+1);//更新结果
                sum -= nums[left++];//更新sum值 并出窗口
            }
        }
        return len == Integer.MAX_VALUE ? 0 : len;//对len进行判断,以免找不到返回的值为最大MAX
}

复杂度分析:

时间复杂度:这里虽然使用了两个while循环,但是判断阶段while循环的循环次数可以忽略不计,从始至终,都是left,right将整个数组进行遍历 ,所以空间复杂度是O(N)。

空间复杂度:从始至终都没有创建数组,使用有限的变量便解决了问题,所以空间复杂度是O(1).

                                                                          完!!!

觉得本博客不错的记得一定记得一件三连!!! 有错误请指出,一定知错就改!!!!


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值