Grokking Google Coding Interview
Ask Author
Back to course home

0% completed

Vote For New Content
Solution: Shortest Subarray with Sum at Least K
Table of Contents

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

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

Python3
Python3

. . . .

Complexity Analysis

Time Complexity

  • O(n): 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

  • O(n): 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 O(n).

.....

.....

.....

Like the course? Get enrolled and start learning!

Table of Contents

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible