长度最小的子数组——滑动窗口

209. 长度最小的子数组 - 力扣(LeetCode)

1.暴力解法

暴力解法 我的思路是用一个for循环 嵌套一个while循环

然后用q进行计数 看是到达第几个的时候 会大于等于target

时间复杂度是O(n^2);

空间复杂度是O(n);

但是我们会发现在长度很长的数组的时候它会超时。

class Solution {
    public int minSubArrayLen(int target, int[] nums){
        int h = 0;
        for(int i = 0;i<nums.length;i++)
        {
            h+=nums[i];
        }
        if(h<target) return 0;//特殊情况就是全加上了还是太小 所以我们就需要直接return 0
        int min = Integer.MAX_VALUE;
        for(int i = 0;i<nums.length;i++)
        {
            int q = 1;//计数
            int n = nums[i];//从第几个开始
            int m = i+1;//从后面一个开始相加
            while(m<nums.length&&n<target)
            {
                n = n+ nums[m];
                m++;
                q++;
            }//当超过或达到最后一个的时候就跳出循环
            if(q<=min&&n>=target) min = q;
//要不然比如一个数组 他全部加起来是有超过Target的 但是当m变成最后一个的时候 也会跳出那个循环
//并且此时q为1 那么会导致最后的结果不准确
        }
        return min;
    }
}

2.滑动窗口

滑动窗口的精髓在于 用暴力解法的话 就是一遍一遍for循环 推倒重来

但是滑动窗口可以保证 因为起始位置和末尾位置都在改变 所以保证了说效率比较高

原理如下

class Solution {

    // 滑动窗口
    public int minSubArrayLen(int s, int[] nums) {
        int left = 0;
        int sum = 0;
        int result = Integer.MAX_VALUE;
        for (int right = 0; right < nums.length; right++) {
            //为什么right是末尾位置呢 因为我们需要知道 如果是left写在里 
            //是不是就和暴力一样一遍一遍for循环推倒重来
             sum+=nums[right];
            while(sum>=s)//那么为什么要用where呢 是因为比如s是一百 现在是1,1,1,1,1...105
//那么加到最后一个就是106 如果是用if 那么--一个之后 仍然是105 仍然大于 但是我们起始位置要跑到
//下一次让它小于的地方所以用where
            {
                result = Math.min(result, right - left + 1);
                sum -= nums[left++];//这里就是滑动窗口的精髓 起始位置的移动就是在这里移动
            }
            }
                    return result == Integer.MAX_VALUE ? 0 : result;
        }
    }
}

这样时间复杂度就变成了O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值