862. 和至少为 K 的最短子数组

题目链接:

862. 和至少为 K 的最短子数组 - 力扣(LeetCode)

题目:

给你一个整数数组 nums 和一个整数 k ,找出 nums 中和至少为 k 的 最短非空子数组 ,并返回该子数组的长度。如果不存在这样的 子数组 ,返回 -1 。

子数组 是数组中 连续 的一部分。

示例 : 

输入:nums = [-28, 81, -20, 28, -29], k = 89
输出:3

提示:

  • 1 <= nums.length <= 105
  • -105 <= nums[i] <= 105
  • 1 <= k <= 109

代码:

//       i-1| i,|  |
    //      A{2,|-1,|2,|5}
    //    sum{0,| 2,|1,|3,8}
    //    当sum[i]-sum[j]>=key时,下标(i-j)中间的这一段就是要求的子数组之一,之后比较一下每次得出的子数组之长,拿到最短的返回

    public int shortestSubarray(int[] A, int k) {
        int minLength = Integer.MAX_VALUE;//最短子数组长度
        long[] sum = new long[A.length + 1];//用一个数组来记录前n个数之和,从1开始维护方便运算sum[i] = sum[i-1]+A[i-1]
        for (int i = 1; i <= A.length; i++) {//先获取前缀和,因为从1开始的,sum总共就是A.length+1个和
            sum[i] = A[i - 1] + sum[i - 1];
        }
        //错了。。。有负数的情况下,相加后反而会变小;其实是因为少判断了一部分子数组
        //比如这个测试点  A=[-28,81,-20,28,-29],k=89,其实把第一个数去掉就符合要求
        /*for (int i = 1; i <= A.length; i++) {
            if (sum[i] < k) continue;
            for (int j = 0; j < i; j++) {//如果sum[i]大于k,说明满足要求了,然后找长度最短的
                if (sum[i] - sum[j] >= k) {
                    minLength = minLength < i - j ? minLength : i - j;
                    System.out.println(minLength + "\t" + i + "\t" + j);
                }
            }
        }*/
        //使用单调栈;检查一下A[i-1]是不是负数,如果是负数,就不要他了
        //比较sum[i]和sum[i-1],如果变小了,A[i-1]是个负数
        Deque<Integer> deque = new LinkedList<>();
        for (int i = 0; i < sum.length; i++) {
            if (i != 0) {
                while (deque.size() > 0 && sum[deque.peekLast()] >= sum[i]) {
                    //如果sum[i]比sum[i-1]还小,说明A[i-1]是个负数,他不但影响前边的子数组废掉,还会影响后边的数字相加后变小,他得滚蛋,同时把前边的子数组拖下水
                    deque.pollLast();
                }
                //第一次deque.peekFirst是0,在0被出队之前,全都相当于sum[i]>=k
                while (deque.size() > 0 && sum[i] - sum[deque.peekFirst()] >= k) {
                    //如果子数组满足要求了,尝试去掉最前边的数字来找到最短的子数组
                    minLength = Math.min(minLength, i - deque.peekFirst());
                    deque.pollFirst();
                }
            }
            deque.offerLast(i);
        }
        return minLength == Integer.MAX_VALUE ? -1 : minLength;//如果minLength还是Max_Value,说明不存在满足要求的,返回-1
    }

思路都在注释了,看的一些大佬的思路,一开始自己写,没想到用单调栈进行优化。关键是要想到用前缀和,sum[ i ] = sum[i - 1]+A[i - 1]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值