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 <= A.length <= 50000
- -10 ^ 5 <= A[i] <= 10 ^ 5
- 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 时,记录一下当前长度,队首就可以出队了。
易错点:
- 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++)