Shortest Subarray with Sum at Least K
HardUpdated: Aug 2, 2025
Practice on:
Problem
Given an integer array nums and an integer k, return the length of the shortest non-empty subarray of nums with a sum of at least k. If there is no such subarray, return -1.
A subarray is a contiguous part of an array.
Examples
Example 1:
Input: nums = [1], k = 1
Output: 1
Example 2:
Input: nums = [1,2], k = 4
Output: -1
Example 3:
Input: nums = [2,-1,2], k = 3
Output: 3
Solution
Method 1 - Prefix sum + Monotonic queue
- Prefix Sum and Monotonic Queue:
- We use a prefix sum array to keep track of cumulative sums.
- A deque (double-ended queue) is used to maintain indices of the prefix sum array in increasing order.
- For each index
i, while there are indices in the deque and the prefix sum difference between the current index and the front of the deque is at leastK, we update the minimum length. - We maintain the deque such that it helps to find the smallest subarray with the required sum efficiently.
- Steps:
- Initialise a deque and the prefix sum array.
- Traverse the prefix sum array.
- For each element, ensure that the elements in the deque are increasing.
- Calculate the potential minimum length whenever the required sum condition is met.
Code
Java
class Solution {
public int shortestSubarray(int[] nums, int k) {
int n = nums.length;
long[] prefixSum = new long[n + 1];
for (int i = 0; i < n; i++) {
prefixSum[i + 1] = prefixSum[i] + nums[i];
}
Deque<Integer> dq = new LinkedList<>();
int ans = Integer.MAX_VALUE;
for (int i = 0; i < prefixSum.length; i++) {
while (!dq.isEmpty() && prefixSum[i] - prefixSum[dq.peekFirst()] >= k) {
ans = Math.min(ans, i - dq.pollFirst());
}
while (!dq.isEmpty() && prefixSum[i] <= prefixSum[dq.peekLast()]) {
dq.pollLast();
}
dq.addLast(i);
}
return ans == Integer.MAX_VALUE ? -1 : ans;
}
}
Python
class Solution:
def shortestSubarray(self, nums: List[int], k: int) -> int:
n = len(nums)
prefix_sum = [0] * (n + 1)
for i in range(n):
prefix_sum[i + 1] = prefix_sum[i] + nums[i]
dq = deque()
ans = float('inf')
for i in range(len(prefix_sum)):
while dq and prefix_sum[i] - prefix_sum[dq[0]] >= k:
ans = min(ans, i - dq.popleft())
while dq and prefix_sum[i] <= prefix_sum[dq[-1]]:
dq.pop()
dq.append(i)
return ans if ans != float('inf') else -1
Complexity
- ⏰ Time complexity:
O(n)because each element is processed at most twice (once added and once removed from the deque). - 🧺 Space complexity:
O(n), due to the extra space used for the prefix sum array and the deque.