LeetCode209.长度最小的子数组

本文探讨了如何用滑动窗口技巧和二分查找优化求解LeetCode 209题,提供了两种方法:一是通过维护左右边界动态调整,二是先累加数组后用二分找到满足目标和的最小子区间。两种方法对比,展示了在不同场景下的高效解决方案。
摘要由CSDN通过智能技术生成

题目链接

LeetCode209.长度最小的子数组

整体思路

我首先想到的解答方法是采用滑动窗口,题目底部提到使用O(nlogn)的方法去解决,所以又想了第二种解答方法,即进行累加再采用二分的方法查找。

详细解答

1.滑动窗口的方法

先取l=0,r=0,然后l不变,r向右滑动直到[l,r)区间的数字之和sum>=target(若不存在则答案为0),此时我们可以得到以l为下限得到的最小答案。然后将l右滑,r固定,直到sum-nums[l]<target,此时我们又可以得到一个答案,将目前得到的答案和之前的答案进行比较,取最小值,不断重复上述步骤,直到所有r>=nums.length。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int l=0,r=0;
        int sum=0;
        int ans=nums.length+1;
        while (r<nums.length){
            while(sum<target&&r<nums.length)
                sum+=nums[r++];
            if(sum>=target)
                    ans=Math.min(ans,r-l);
            while (sum>=target&&l<r){
                sum-=nums[l++];
                if(sum>=target)
                    ans=Math.min(ans,r-l);
            }
        }
        if(ans==nums.length+1)
            ans=0;
        return ans;
    }
}

2.遍历+二分的方法

注意到数组中的所有值都是正整数,所以对数组进行累加就可以得到一个递增的数组。以每个数字为子区间最左边的数字,采用二分查找的方法得到以该数字为下限的最小子区间即可,取遍历得到的最小子区间长度为答案。

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int l,r;
        int ans=nums.length+1;
        for(int i=1;i<nums.length;i++)
            nums[i]+=nums[i-1];
        for(int i=0;i<nums.length;i++){
            l=i;
            r=nums.length-1;  //左闭右闭
            int presum=i==0?0:nums[i-1];
            int sum=0;
            while(l<=r) {
                int m=(l+r)/2;
                sum=nums[m]-presum;
                if(sum<target)
                    l=m+1;
                else if(sum==target) {
                    l=m;
                    break;
                }
                else
                    r=m-1;
            }
            if(sum>=target)
                ans=Math.min(ans,l-i+1);
        }
        if(ans==nums.length+1)
            ans=0;
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值