862. Shortest Subarray with Sum at Least K

本文介绍了如何利用单调队列解决寻找数组中和至少为K的最短子数组的问题。通过分析滑动窗口和单调队列的特点,阐述了单调队列在此问题中的应用,以及解决此类问题的复杂度和常见易错点。
摘要由CSDN通过智能技术生成

862. Shortest Subarray with Sum at Least K


Return the length of the shortest, non-empty, contiguous subarray of A with sum at least K.

If there is no non-empty subarray with sum at least K, return -1.

Example 1:

Input: A = [1], K = 1
Output: 1

Example 2:

Input: A = [1,2], K = 4
Output: -1

Example 3:

Input: A = [2,-1,2], K = 3
Output: 3

Note:

  1. 1 <= A.length <= 50000
  2. -10 ^ 5 <= A[i] <= 10 ^ 5
  3. 1 <= K <= 10 ^ 9

方法1: monotonic queue

https://leetcode.com/problems/shortest-subarray-with-sum-at-least-k/discuss/204290/Monotonic-Queue-Summary
LC84. Largest Rectangle in Histogram
LC239. Sliding Window Maximum
LC739. Daily Temperatures
LC862. Shortest Subarray with Sum at Least K
LC901. Online Stock Span
LC907. Sum of Subarray Minimums

思路:

为什么会用到了单调队列的方法呢?首先来看,我们的目标是找到presum[i] - presum[j] >= k 的最短subarray。用sliding window的方法来说,左手边的presum只有在很小的时候才有竞争力,否则假设 i < j, presum[j] > [i], 那么对于后面的 某个数 q来讲,如果[j … q ]能够大于 K, [i… q]一定也大于K,此时两者都qualified,但是因为队尾代表的subarray长度更长,一定不会是结果。所以当后面的presum小于队尾的presum时,队尾彻底失去竞争力,被pop。这就使得我们的queue事实上是单调递增presum的index队列。那么对于单调递增队列来说,队首的元素什么时候过期呢?对于队首 i 来讲,如果presum[j], presum[m] 都满足 presum[j] - presum[i] >= k, presum[m] - presum[i] >= k, 同时j < m,那么[i, …, m]一定不会被考虑,因为长度更长,也就是说 i 不会愿意和 j 以后的任何m组cp。所以当第一次遇到满足 presum[j] - presum[i] >= k的 j 时,记录一下当前长度,队首就可以出队了。

易错点:

  1. for (int i = 0; i < n + 1; i++) ,这个循环如果不从0开始,就一定要提前push进一个0: 这和我们queue里面存的index含义有关,我们之后会抽出这个值,计算(i, j]之间的subarray,也就是左端点之前的一点。如果没有这个0,任何形似似[0,i]的候选值都不会被考虑,毕竟只有非空的时候才会被update。

Complexity

Time complexity: O(n)
Space complexity: O(n)

class Solution {
   
public:
    int shortestSubarray(vector<int>& A, int K) {
   
        int n = A.size(), result = n + 1;
        vector<int> presum(n + 1, 0);
        for (int i = 1; i < n + 1; i++) {
   
            presum[i] = presum[i - 1] + A[i - 1];
        }
        deque<int> monoq;
        for (int i = 0; i < n + 1; i++)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值