美文网首页
862. 和至少为 K 的最短子数组(难度:困难)

862. 和至少为 K 的最短子数组(难度:困难)

作者: 一直流浪 | 来源:发表于2022-12-18 10:55 被阅读0次

题目链接:https://leetcode.cn/problems/shortest-subarray-with-sum-at-least-k/

题目描述:

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

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

示例 1:

输入:nums = [1], k = 1
输出:1

示例 2:

输入:nums = [1,2], k = 4
输出:-1

示例 3:

输入:nums = [2,-1,2], k = 3
输出:3

提示:

  • 1 <= nums.length <= 10^5
  • -10^5 <= nums[i] <= 10^5
  • 1 <= k <= 10^9

解法:前缀和+单调队列

定义一个数组dp,用来存放前缀和。即dp[i] 表示 从下标0 到下标 i-1的元素之和。

前缀和:前n位的和。

这样可以将之前的一个连续子数组和转换为前缀和之差。例如,下标i到下标j子数组之和,j>i,可以表示为dp[j + 1] - dp[i]。

计算nums 的前缀和dp之后,使用暴力算法,枚举所有满足 i > j,且 dp[i] - dp[j] >= k的子数组,找到长度最短的一个。

我们利用一个双向队列deque来存放所有遍历过的下标i。

我们可以通过去除 deque 中的元素,从而提高效率。

优化点:

(1)遍历到 dp[i] 时,若左边某个 dp[j],满足 dp[i] - dp[j] >= k,那么无论dp[i] 的右边的数字是大是小,都不可能把j作为起点,找到长度小于 i - j 的满足条件的子数组,因此 dp[j] 已经没有用,可以退出队列deque。

(2)遍历到 dp[i] 时,若左边某个 dp[j],满足 dp[i] <= dp[j],若后续遍历有个元素x,满足 x - dp[j] >= k,那么一定有 x - dp[i] >= k,由于 xi 的距离一定是小于 j 的,因此 dp[j] 已经没有用了,可以退出队列。

代码:

class Solution {
    public int shortestSubarray(int[] nums, int k) {
        int len = nums.length;
        long[] dp = new long[len + 1];
        for (int i = 0; i < len; i++) {
            dp[i + 1] = dp[i] + nums[i];
        }

        int result = len + 1;
        Deque<Integer> deque = new ArrayDeque<>();
        for (int i = 0; i <= len; i++) {
            long temp = dp[i];
            while (!deque.isEmpty() && temp - dp[deque.peekFirst()] >= k) {
                result = Math.min(result, i - deque.pollFirst());
            }
            while (!deque.isEmpty() && dp[deque.peekLast()] >= temp) {
                deque.pollLast();
            }
            deque.offerLast(i);
        }
        return result == len + 1 ? -1 : result;
    }
}

相关文章

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

    返回 A 的最短的非空连续子数组的长度,该子数组的和至少为 K 。如果没有和至少为 K 的非空子数组,返回 -1。...

  • leetcode 560. 和为K的子数组

    560. 和为K的子数组 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。示例 ...

  • 560.和为K的子数组

    和为K的子数组 题目 给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。 示例 1...

  • 前缀和

    560.和为K的子数组 算出一共有几个和为 k 的子数组。这里用到了前缀和数组。 注意以下几点: 前缀和数组第0号...

  • 算法15 Continuous Subarray Sum

    题目:给定一个非负数列表和一个目标整数 k,编写一个函数来检查数组是否有连续的子数组,其大小至少为2,总和为k的倍...

  • 和为K的子数组

    题目描述 https://leetcode-cn.com/problems/subarray-sum-equals...

  • 和为k的子数组

    classSolution{ publicintsubarraySum(int[]nums,intk){ int[...

  • LeetCode 560 和为k的子数组

    LeetCode 560 和为k的子数组 题目描述: 代码:

  • 连续的子数组和

    给定一个包含 非负数 的数组和一个目标 整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,...

  • leetcode第八百六十二题—和至少为K的最短子数组

    这道题有点意思,双指针思路有了,但是情况考虑不全了,还需要加强。 1.题目 原题 返回 A 的最短的非空连续子数组...

网友评论

      本文标题:862. 和至少为 K 的最短子数组(难度:困难)

      本文链接:https://www.haomeiwen.com/subject/kxbctdtx.html