Knowledge Guide
HomeDSACompany Practice

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

  1. 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.

  2. 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.

  3. 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 the nums. 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

  1. 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.

  2. 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.

  3. 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 the nums. 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

  1. Initialize Prefix Sums: Create an array prefixSums of size n+1 (where n is the size of the input array nums). The first element of prefixSums is 0. Populate this array such that each element prefixSums[i] represents the sum of the first i elements of nums. This helps in calculating the sum of any subarray quickly.

  2. Initialize Variables: Define an integer result to store the minimum length of the subarray found so far and set it to Integer.MAX_VALUE or its equivalent in the implementation language as an initial value. Also, create a deque (double-ended queue) deque to store indices of elements in prefixSums which are potential starting points of subarrays.

  3. Iterate Through Prefix Sums: Loop through the prefixSums array. For each index i, perform the following steps:

    • Dequeue Front: While the deque is not empty and the difference between prefixSums[i] and prefixSums[deque.front] is greater than or equal to k, update result with the smaller of the current result and i - 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 to prefixSums[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 i to the back of the deque.
  4. Check for No Solution: If result remains Integer.MAX_VALUE, it means no valid subarray was found. Return -1 in this case.

  5. Return Result: Otherwise, return result as the length of the shortest subarray with a sum of at least k.

Algorithm Walkthrough

Let's consider the Input: nums = [1, -1, 5, 2, 3, 4, 3, 2], k = 8

  1. Initialize Prefix Sums: prefixSums = [0, 1, 0, 5, 7, 10, 14, 17, 19]
  2. Set result to Infinity (or the equivalent, like Integer.MAX_VALUE), and initialize an empty deque deque.

Iteration Process

  • i=0: Add 0 to deque. So, deque: [0].
  • i=1: Add 1 to deque. So, deque: [0, 1].
  • i=2: Pop 1 from the back of deque since prefixSums[2] <= prefixSums[1], then add 2 to deque. So, deque: [0, 2].
  • i=3: prefixSums[3] - prefixSums[deque.front (0)] = 5, not enough, add 3 to deque. So, deque: [0, 2, 3].
  • i=4: prefixSums[4] - prefixSums[deque.front (0)] = 7, still not enough, add 4 to deque. So, deque: [0, 2, 3, 4].
  • i=5: prefixSums[5] - prefixSums[deque.front (0)] = 10. Now, 10 >= 8, so update result = min(result, 5 - 0) = 5 and pop 0 from deque.front. Then, prefixSums[5] - prefixSums[deque.front (2)] = 10, update result = min(result, 5 - 2) = 3 and pop 2. No more updates, add 5 to deque. So, deque: [3, 4, 5].
  • i=6: prefixSums[6] - prefixSums[deque.front (3)] = 14-5 = 9. Now, 9 >= 8, so update result = min(result, 6 - 3) = 3 and pop 3 from deque.front, and add 6 to the deque. Now, deque = [4, 5, 6].
  • i=7: prefixSums[7] - prefixSums[deque.front (4)] = 17 - 7 = 10. Now, 10 >= 8, so update result = min(result, 7 - 4) = 3 and pop 4 from deque.front, and add 7 to the deque. Now, deque = [5, 6, 7].
  • i=8: prefixSums[8] - prefixSums[deque.front (5)] = 19 - 10 = 9. Now, 9 >= 8, so update result = min(result, 8 - 5) = 3 and pop 5 from deque.front, and add 8 to 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

java
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 (where n is 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.

🪜 Hint ladder (no spoilers)

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.
🎨 Explain the approach visually

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.
🔍 Review my solution

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.
🔁 Drill the pattern

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.

📝 My notes