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

Posted 不吐西瓜籽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了862. 和至少为 K 的最短子数组相关的知识,希望对你有一定的参考价值。

算法记录

LeetCode 题目:

  返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。



说明

一、题目

  如果没有和至少为 K 的非空子数组,返回 -1 。

二、分析

  • 首先看测试的样例数据就知道暴力肯定会超时, 那就只能观察一下题目的规则来寻求比较优质的解法了.
  • 题意寻找的是一段连续区间之和, 而且区间之和需要大于一个数值, 说到区间之和的求解, 我们就可以先把前序和给算出来备用.
  • ij 前序和的差值也就意味着区间 i~j 的和, 这样的话就好办了, 只需要遍历整个前序和, 找出距离最小的满足条件的区间不就可以了么, 但是这样也会进行暴力, 有没有好一点的解法呢?
  • 再看如果我们已经拿到了一个区间满足条件, 我们继续找其他的区间和判断是否还有优于这个解的, 如果 j 继续往后走, 区间距离是不是就增大了, 肯定不是优解, 如果 i 往后走, 找到一个比当前的点还要小的值, 也就是同样满足条件而且距离还更小, 就会更新最优.
  • 分析过后会发现每次寻找的更新解是一个不增的序列, 也就可以用一个单调队列来进行状态的额保存.
class Solution {
    public int shortestSubarray(int[] nums, int k) {
        long[] sum = new long[nums.length + 1];
        for (int i = 1; i <= nums.length; i++) sum[i] = sum[i - 1] + nums[i - 1];
        Deque<Integer> queue = new LinkedList<>();
        int minLength = sum.length;
        for (int i = 0; i < sum.length; i++) {
            while (!queue.isEmpty() && sum[queue.peekLast()] >= sum[i]) queue.pollLast();
            while (!queue.isEmpty() && sum[i] - sum[queue.peekFirst()] >= k) {
                minLength = Math.min(minLength, i - queue.pollFirst());
            }
            queue.addLast(i);
        }
        if (minLength == sum.length) return -1;
        else return minLength;
    }
}

总结

熟悉前缀和方法和单调队列的使用。

以上是关于862. 和至少为 K 的最短子数组的主要内容,如果未能解决你的问题,请参考以下文章

⭐算法入门⭐《队列 - 单调队列》困难03 —— LeetCode 862. 和至少为 K 的最短子数组

862. 和至少为 K 的最短子数组(困难)-前缀和单调双端队列

力扣 每日一题 862. 和至少为 K 的最短子数组难度:困难,rating: 2306(前缀和+单调队列)

力扣 每日一题 862. 和至少为 K 的最短子数组难度:困难,rating: 2306(前缀和+单调队列)

LeetCode 862 和至少为K的最短子数组[前缀和 双端队列] HERODING的LeetCode之路

和至少为K的最短子数组