hard Shortest Subarray with Sum at Least K
Problem Statement
Given an array of integers nums and a positive integer k, return the minimum length of the non-empty subarray of nums such that sum of its elements should be at least k. If there is no such subarray, return -1.
A subarray is defined as a contiguous sequence of an array.
Examples
-
Input: nums = [1, 2, 3, 4, 5], k = 11
Expected Output: 3
Justification: The shortest subarray with a sum of at least 11 is [3, 4, 5], which has a length of 3. -
Input: nums = [1, -1, 5, 2, 3, 4, 3, 2], k = 8
Expected Output: 3
Justification: The shortest subarray with a sum of at least 8 is [5, 2, 3], which has a length of 2. -
Input: nums = [-1, -1, -2, -3], k = 2
Expected Output: -1
Justification: The shortest subarray with a sum of at least 2 is not exist in thenums. So, the answer is-1.
Try it yourself
Try solving this question here:
✅ Solution Shortest Subarray with Sum at Least K
Problem Statement
Given an array of integers nums and a positive integer k, return the minimum length of the non-empty subarray of nums such that sum of its elements should be at least k. If there is no such subarray, return -1.
A subarray is defined as a contiguous sequence of an array.
Examples
-
Input: nums = [1, 2, 3, 4, 5], k = 11
Expected Output: 3
Justification: The shortest subarray with a sum of at least 11 is [3, 4, 5], which has a length of 3. -
Input: nums = [1, -1, 5, 2, 3, 4, 3, 2], k = 8
Expected Output: 3
Justification: The shortest subarray with a sum of at least 8 is [5, 2, 3], which has a length of 2. -
Input: nums = [-1, -1, -2, -3], k = 2
Expected Output: -1
Justification: The shortest subarray with a sum of at least 2 is not exist in thenums. So, the answer is-1.
Solution
To solve this problem, the approach involves utilizing a deque (double-ended queue) to keep track of potential starting points of subarrays in a way that efficiently updates the minimum length of the qualifying subarray as the array is iterated. The idea is to maintain a running sum of elements and use the deque to store indices of elements that could serve as starting points of subarrays with sums at least k.
This method is effective because it allows us to add new potential subarray start points while also removing ones that are no longer viable as we move forward through the array. It combines the efficiency of a sliding window approach with the flexibility of a queue to handle negative numbers and varying subarray sizes.
Step-by-Step Algorithm
-
Initialize Prefix Sums: Create an array
prefixSumsof sizen+1(wherenis the size of the input arraynums). The first element ofprefixSumsis0. Populate this array such that each elementprefixSums[i]represents the sum of the firstielements ofnums. This helps in calculating the sum of any subarray quickly. -
Initialize Variables: Define an integer
resultto store the minimum length of the subarray found so far and set it toInteger.MAX_VALUEor its equivalent in the implementation language as an initial value. Also, create a deque (double-ended queue)dequeto store indices of elements inprefixSumswhich are potential starting points of subarrays. -
Iterate Through Prefix Sums: Loop through the
prefixSumsarray. For each indexi, perform the following steps:- Dequeue Front: While the deque is not empty and the difference between
prefixSums[i]andprefixSums[deque.front]is greater than or equal tok, updateresultwith the smaller of the currentresultandi - deque.front. Then, pop the front of the deque. This step removes indices that have found a valid subarray or are too far to contribute to a shorter subarray. - Dequeue Back: While the deque is not empty and
prefixSums[i]is less than or equal toprefixSums[deque.back], pop the back of the deque. This step ensures that the deque always contains indices in increasing order of their prefix sums, which is crucial for quickly finding the shortest valid subarray. - Enqueue Current Index: Add the current index
ito the back of the deque.
- Dequeue Front: While the deque is not empty and the difference between
-
Check for No Solution: If
resultremainsInteger.MAX_VALUE, it means no valid subarray was found. Return-1in this case. -
Return Result: Otherwise, return
resultas the length of the shortest subarray with a sum of at leastk.
Algorithm Walkthrough
Let's consider the Input: nums = [1, -1, 5, 2, 3, 4, 3, 2], k = 8
- Initialize Prefix Sums:
prefixSums = [0, 1, 0, 5, 7, 10, 14, 17, 19] - Set
resultto Infinity (or the equivalent, likeInteger.MAX_VALUE), and initialize an empty dequedeque.
Iteration Process
- i=0: Add
0todeque. So, deque:[0]. - i=1: Add
1todeque. So, deque:[0, 1]. - i=2: Pop
1from the back ofdequesinceprefixSums[2] <= prefixSums[1], then add2todeque. So, deque:[0, 2]. - i=3:
prefixSums[3] - prefixSums[deque.front (0)] = 5, not enough, add3todeque. So, deque:[0, 2, 3]. - i=4:
prefixSums[4] - prefixSums[deque.front (0)] = 7, still not enough, add4todeque. So, deque:[0, 2, 3, 4]. - i=5:
prefixSums[5] - prefixSums[deque.front (0)] = 10. Now,10 >= 8, so updateresult = min(result, 5 - 0) = 5and pop0fromdeque.front. Then,prefixSums[5] - prefixSums[deque.front (2)] = 10, updateresult = min(result, 5 - 2) = 3and pop2. No more updates, add5todeque. So, deque:[3, 4, 5]. - i=6:
prefixSums[6] - prefixSums[deque.front (3)] = 14-5 = 9. Now,9 >= 8, so updateresult = min(result, 6 - 3) = 3and pop3fromdeque.front, and add6to the deque. Now, deque =[4, 5, 6]. - i=7:
prefixSums[7] - prefixSums[deque.front (4)] = 17 - 7 = 10. Now,10 >= 8, so updateresult = min(result, 7 - 4) = 3and pop4fromdeque.front, and add7to the deque. Now, deque =[5, 6, 7]. - i=8:
prefixSums[8] - prefixSums[deque.front (5)] = 19 - 10 = 9. Now,9 >= 8, so updateresult = min(result, 8 - 5) = 3and pop5fromdeque.front, and add8to the deque. Now, deque =[6, 7, 8].
The smallest subarray length that meets the condition k = 8 was found during the iteration for i=5, giving a subarray length of 3 ([5, 2, 3]). Thus, the result is 3.
Code
import java.util.Deque;
import java.util.LinkedList;
public class Solution {
// Method to find the shortest subarray with a sum of at least K
public int shortestSubarray(int[] nums, int k) {
int n = nums.length;
// Array to store prefix sums
long[] prefixSums = new long[n + 1];
for (int i = 0; i < n; i++) {
prefixSums[i + 1] = prefixSums[i] + nums[i];
}
// Initialize the result as Integer.MAX_VALUE
int result = Integer.MAX_VALUE;
// Deque to store indices
Deque<Integer> deque = new LinkedList<>();
for (int i = 0; i < prefixSums.length; i++) {
// Remove elements from the deque if they do not contribute to a shorter subarray
while (
!deque.isEmpty() && prefixSums[i] - prefixSums[deque.getFirst()] >= k
) result = Math.min(result, i - deque.pollFirst());
// Maintain deque properties for the sliding window
while (
!deque.isEmpty() && prefixSums[i] <= prefixSums[deque.getLast()]
) deque.pollLast();
deque.addLast(i);
}
// Return result or -1 if no such subarray exists
return result == Integer.MAX_VALUE ? -1 : result;
}
// Main method to test the examples
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(
solution.shortestSubarray(new int[] { 1, 2, 3, 4, 5 }, 11)
); // Expected output: 3
System.out.println(
solution.shortestSubarray(new int[] { 1, -1, 5, 2, 3, 4, 3, 2 }, 8)
); // Expected output: 3
System.out.println(
solution.shortestSubarray(new int[] { -1, -1, -2, -3 }, 2)
); // Expected output: -1
}
}
Complexity Analysis
Time Complexity
: The algorithm iterates through the input array once to construct the prefix sum array. During this iteration, for each element, operations within the deque (adding or removing indices) also occur. Despite the nested appearance of deque operations within the loop, each index is added once and removed at most once, leading to a linear complexity overall. The operations on the deque are constant time on average, so the overall time complexity remains linear with respect to the size of the input array.
Space Complexity
: The algorithm requires additional space for the prefix sums array, which stores the cumulative sum up to each index and has a length of n + 1(wherenis the length of the input array). The deque used for maintaining the current window of indices has a space complexity that varies but in the worst case, could contain all indices of the array, leading to a linear space complexity. Therefore, the total space complexity is.
🤖 Don't fully get this? Learn it with Claude
Stuck on Shortest Subarray with Sum at Least K? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Shortest Subarray with Sum at Least K** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Shortest Subarray with Sum at Least K** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Shortest Subarray with Sum at Least K**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Shortest Subarray with Sum at Least K**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.