Shortest Subarray with Sum at Least K

hard prefix sum deque monotonic queue

Problem

Given an integer array nums and an integer k, return the length of the shortest non-empty contiguous subarray whose sum is at least k. If no such subarray exists, return -1. Values may be negative, so a plain sliding window does not work.

Inputnums = [2, -1, 2], k = 3
Output3
The whole array sums to 3; no shorter subarray reaches 3.

from collections import deque

def shortest_subarray(nums, k):
    n = len(nums)
    P = [0] * (n + 1)
    for i in range(n):
        P[i + 1] = P[i] + nums[i]
    dq, ans = deque(), n + 1
    for y in range(n + 1):
        while dq and P[y] - P[dq[0]] >= k:
            ans = min(ans, y - dq.popleft())
        while dq and P[dq[-1]] >= P[y]:
            dq.pop()
        dq.append(y)
    return ans if ans <= n else -1
function shortestSubarray(nums, k) {
  const n = nums.length, P = [0];
  for (let i = 0; i < n; i++) P.push(P[i] + nums[i]);
  const dq = [];           // indices, P increasing
  let ans = n + 1;
  for (let y = 0; y <= n; y++) {
    while (dq.length && P[y] - P[dq[0]] >= k)
      ans = Math.min(ans, y - dq.shift());
    while (dq.length && P[dq[dq.length - 1]] >= P[y])
      dq.pop();
    dq.push(y);
  }
  return ans <= n ? ans : -1;
}
int shortestSubarray(int[] nums, int k) {
    int n = nums.length;
    long[] P = new long[n + 1];
    for (int i = 0; i < n; i++) P[i + 1] = P[i] + nums[i];
    Deque<Integer> dq = new ArrayDeque<>();
    int ans = n + 1;
    for (int y = 0; y <= n; y++) {
        while (!dq.isEmpty() && P[y] - P[dq.peekFirst()] >= k)
            ans = Math.min(ans, y - dq.pollFirst());
        while (!dq.isEmpty() && P[dq.peekLast()] >= P[y])
            dq.pollLast();
        dq.addLast(y);
    }
    return ans <= n ? ans : -1;
}
int shortestSubarray(vector<int>& nums, int k) {
    int n = nums.size();
    vector<long long> P(n + 1, 0);
    for (int i = 0; i < n; i++) P[i + 1] = P[i] + nums[i];
    deque<int> dq; int ans = n + 1;
    for (int y = 0; y <= n; y++) {
        while (!dq.empty() && P[y] - P[dq.front()] >= k)
            ans = min(ans, y - dq.front()), dq.pop_front();
        while (!dq.empty() && P[dq.back()] >= P[y])
            dq.pop_back();
        dq.push_back(y);
    }
    return ans <= n ? ans : -1;
}
Time: O(n) Space: O(n)