leetcode 算法-长度最小的子数组-209

leetcode 算法-长度最小的子数组

leetcode 传送门

题目

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。

示例:

输入: s = 7, nums = [2,3,1,2,4,3]
输出: 2
解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。

解题思路

我们使用变量min来记录满足条件的最小的连续子数组的长度,使用sum来记录和,n来记录当前连续数组的长度。

首先我们还是遍历原数组,先处理特殊情况:

当当前元素值>=s的时候,直接返回1,因为长度不可能小于1;

当当前元素值<s的时候,sum累加元素值,n++;如果sum>=s,可以确定nums[i]之前的n-1个元素的和是小于s的,但是我们无法确定累加的开始元素到当前元素的长度是不是最小,因为有可能不需要开始元素sum也可能大于s,有可能是因为当前元素非常大。

因此我们首先需要判断sum-nums[j]是否大于等于s,如果满足,每次让sum减去nums[j++],判断减去之后的sum是否还大于等于s,如果依然符合条件,则更新min值,继续判断,直到sum-nums[j]<s,则结束。

如果我们发现sum-nums[j]<s,那么可以直接和min比较,然后决定是否更新min值,更新结束之后,之后我们下一个寻找的肯定是min-1,如何才能最快找到min-1个元素的和大于等于s呢?

我们可以利用已有的min个元素中的后min-2个元素,然后外加下一个元素,这样就可以最快找到min-1个元素的和大于等于s。

代码

class Solution {
    public int minSubArrayLen(int s, int[] nums) {
        int min = Integer.MAX_VALUE,sum=0,n=0;
        for (int i = 0; i <nums.length; i++) {
            if(nums[i]>=s)return 1;
            sum+=nums[i];
            n++;
            if(sum>=s){
                int j=i-n+1;
                if(sum-nums[j]>=s){
                    do{
                        sum -= nums[j++];
                        min = Math.min(min, --n);
                    }while (sum - nums[j] >= s);
                }else{
                    if(n<min)min=n;
                    while(i-j>min-3){
                        sum -= nums[j++];
                        n--;
                    }
                }
            }
        }
        return min==Integer.MAX_VALUE?0 : min;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值