Skip to main content

Sliding Window

Minimum Size Subarray Sum

Problem Description

Given an array of positive integer nums and a positive integer target, return the minimal length of a subarray whose sum is greater than or equal to the target. If there is no such subarray, return 0 instead.

What is a Subarray ?

It's a sequence of elements taken from the original array that are next to each other, without skipping any elements.
For the array [1, 2, 3, 4], here are all possible subarrays:

Single element subarrays:
[1], [2], [3], [4]

Subarrays of length 2:
[1, 2], [2, 3], [3, 4]

Subarrays of length 3:
[1, 2, 3], [2, 3, 4]

Subarray of length 4:
[1, 2, 3, 4] (the entire array)

Note:- { 1, 3 ,4 } or { 2,4 } are not the subarrays of arr[ ] = { 1 , 2 , 3 , 4 }

Examples of Minimum Size Subarray Sum

Input: target = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: There are no subarrays of size 1 that are greater than or equal to the target. Moving forward with the subarray of size 2, the subarray [4,3] has a minimal length under the problem constraint.

Input: target = 4, nums = [1,4,4]
Output: 1
Explanation: The subarray [4] which is of size 1 has the minimal length under the problem constraint.

Input: target = 11, nums = [1,1,1,1,1,1,1,1]
Output: 0
Explanation: Since, the sum of all numbers of nums are less than target, so we can conclude that there are no subarrays with the problem constraint.

Constraints:

  • 1 <= target <= 10^9
  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^4

The solution for the problem statement involves solving it through brute force method or two pointers/sliding window algorithm or by using Binary Search. Each of the methods have their own benefits according to the constraints provided. Let's find it one by one !!

Brute Force Approach (Generate All Subarray)

Intuition

Since, the problem statement asked us to find the the minimal length of a subarray whose sum is greater than or equal to target.
Why not generate every possible subarrays and then finalize which subarray has the minimum length with a sum is greater than or equal to target?

How to generate Subarray of an Array ?

Pick a starting point (i): This can be any index from 0 to n-1 (where n is the length of the array).
Pick an ending point (j): This can be any index from the current starting point i to n-1.
Extract the subarray: Once you have both the starting (i) and ending (j) points, you can extract the subarray by slicing from index i to j (inclusive).

For arr = [1, 2, 3]:
Start at i = 0:
Subarray [1] (from i = 0 to j = 0)
Subarray [1, 2] (from i = 0 to j = 1)
Subarray [1, 2, 3] (from i = 0 to j = 2)

Start at i = 1:
Subarray [2] (from i = 1 to j = 1)
Subarray [2, 3] (from i = 1 to j = 2)

Start at i = 2:
Subarray [3] (from i = 2 to j = 2)

While we generate a subarray, we will update the length of the subarray if the sum is greater than or equal to the target and if its length is less than the previous value.

Minimum Size Subarray Sum
Minimum Size Subarray Sum
Minimum Size Subarray Sum

How To Approach This Problem

  • The outer loop iterates over each possible starting index i.
  • For each starting index i, the inner loop iterates over j (the ending index of the subarray), calculating the cumulative sum.
  • Once the sum is greater than or equal to the target, we update minLength with the current subarray length and break the inner loop for efficiency.
  • If no valid subarray is found, minLength will remain an Integer.MAX_VALUE, and we return 0.

Dry-Run

nums[] = { 4 , 2 , 3 , 6 , 1 , 2 , 7 }
target= 9
Answer:- 2
Explantion:- The subarray [2,7] or [3,6] has sum 9 of size 2.

Initial Values
minLength = Integer.MAX_VALUE
Outer Loop - Iterating over each starting index i
i = 0

Start from nums[0] = 4
Inner loop:
j = 0, sum = 4 (sum is less than target, continue)
j = 1, sum = 4 + 2 = 6 (sum is less than target, continue)
j = 2, sum = 6 + 3 = 9 (sum equals target)
Update minLength = min(Integer.MAX_VALUE, 2 - 0 + 1) = 3
Break inner loop for i = 0 since we met the target.
i = 1

Start from nums[1] = 2
Inner loop:
j = 1, sum = 2 (sum is less than target, continue)
j = 2, sum = 2 + 3 = 5 (sum is less than target, continue)
j = 3, sum = 5 + 6 = 11 (sum is greater than target)
Update minLength = min(3, 3 - 1 + 1) = 3 (no change as it's still 3)
Break inner loop for i = 1.
i = 2

Start from nums[2] = 3
Inner loop:
j = 2, sum = 3 (sum is less than target, continue)
j = 3, sum = 3 + 6 = 9 (sum equals target)
Update minLength = min(3, 3 - 2 + 1) = 2
Break inner loop for i = 2 since we met the target with a shorter subarray.
i = 3

Start from nums[3] = 6
Inner loop:
j = 3, sum = 6 (sum is less than target, continue)
j = 4, sum = 6 + 1 = 7 (sum is less than target, continue)
j = 5, sum = 7 + 2 = 9 (sum equals target)
Update minLength = min(2, 5 - 3 + 1) = 2 (no change as it's still 2)
Break inner loop for i = 3.
i = 4

Start from nums[4] = 1
Inner loop:
j = 4, sum = 1 (sum is less than target, continue)
j = 5, sum = 1 + 2 = 3 (sum is less than target, continue)
j = 6, sum = 3 + 7 = 10 (sum is greater than target)
Update minLength = min(2, 6 - 4 + 1) = 2 (no change as it's still 2)
Break inner loop for i = 4.
i = 5

Start from nums[5] = 2
Inner loop:
j = 5, sum = 2 (sum is less than target, continue)
j = 6, sum = 2 + 7 = 9 (sum equals target)
Update minLength = min(2, 6 - 5 + 1) = 2 (no change as it's still 2)
Break inner loop for i = 5.
i = 6

Start from nums[6] = 7
Inner loop:
j = 6, sum = 7 (sum is less than target, no further j values to check for i = 6)

Final Result
minLength = 2
The minimum length of a subarray with a sum of at least 9 is 2, which corresponds to the subarrays [6, 3] or [2, 7].

Brute Force in all Languages
1. C++ Try on Compiler
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int minLength = INT_MAX;  // Initialize minimum length to a large value
    
        // Iterate over each possible starting point of subarrays
        for (int i = 0; i < nums.size(); i++) {
            int sum = 0;  // Initialize sum for the current subarray
            
            // Iterate to find the minimal subarray length for starting index i
            for (int j = i; j < nums.size(); j++) {
                sum += nums[j];  // Add current element to the sum
                
                // Check if the current sum is >= target
                if (sum >= target) {
                    minLength = min(minLength, j - i + 1);  // Update minimum length
                    break;  // Break inner loop as we found a valid subarray for this start point
                }
            }
        }
        
        // Return the result, 0 if no valid subarray was found
        return minLength == INT_MAX ? 0 : minLength;
    }
};

2. Java Try on Compiler
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int minLength = Integer.MAX_VALUE;  // Initialize minimum length to a large value
        
        // Iterate over each possible starting point of subarrays
        for (int i = 0; i < nums.length; i++) {
            int sum = 0;  // Initialize sum for the current subarray
            
            // Iterate to find the minimal subarray length for starting index i
            for (int j = i; j < nums.length; j++) {
                sum += nums[j];  // Add current element to the sum
                
                // Check if the current sum is >= target
                if (sum >= target) {
                    minLength = Math.min(minLength, j - i + 1);  // Update minimum length
                    break;  // Break inner loop as we found a valid subarray for this start point
                }
            }
        }
        
        // Return the result, 0 if no valid subarray was found
        return minLength == Integer.MAX_VALUE ? 0 : minLength;
    }
}

3. Python Try on Compiler
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        min_length = float('inf')  # Initialize minimum length to a large value
    
        # Iterate over each possible starting point of subarrays
        for i in range(len(nums)):
            sum = 0  # Initialize sum for the current subarray
            
            # Iterate to find the minimal subarray length for starting index i
            for j in range(i, len(nums)):
                sum += nums[j]  # Add current element to the sum
                
                # Check if the current sum is >= target
                if sum >= target:
                    min_length = min(min_length, j - i + 1)  # Update minimum length
                    break  # Break inner loop as we found a valid subarray for this start point

        # Return the result, 0 if no valid subarray was found
        return 0 if min_length == float('inf') else min_length

4. JavaScript Try on Compiler
/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function(target, nums) {
    let minLength = Infinity;  // Initialize minimum length to a large value
    
    // Iterate over each possible starting point of subarrays
    for (let i = 0; i < nums.length; i++) {
        let sum = 0;  // Initialize sum for the current subarray
        
        // Iterate to find the minimal subarray length for starting index i
        for (let j = i; j < nums.length; j++) {
            sum += nums[j];  // Add current element to the sum
            
            // Check if the current sum is >= target
            if (sum >= target) {
                minLength = Math.min(minLength, j - i + 1);  // Update minimum length
                break;  // Break inner loop as we found a valid subarray for this start point
            }
        }
    }
    
    // Return the result, 0 if no valid subarray was found
    return minLength === Infinity ? 0 : minLength;
};

Time Complexity: O(n^2)

The minSubArrayLen function iterates over all possible subarrays in a brute-force manner. Here's how the time complexity is determined:

Outer Loop (Index i): This loop runs from 0 to nums.length - 1, so it executes n times (where n is the length of nums).

Inner Loop (Index j): For each starting index i, the inner loop iterates from i to nums.length - 1, resulting in an increasing number of subarrays being checked as i moves from the beginning to the end of nums.


In the worst case, the number of iterations in the inner loop will be n - i for each i, where i goes from 0 to n - 1.

The overall Time Complexity is : O(n^2).

Space Complexity: O(n)

Auxiliary space complexity refers to the extra space used by the algorithm, excluding the input size.
In this code:

  1. Variables: Only a few constant-space variables are used (minLength, sum).

Thus, auxiliary space complexity: O(1).

Total Space Complexity
Total space complexity includes both the input space and the auxiliary space:

  1. Input Space: The input array nums takes up O(n) space.
  2. Auxiliary Space: As analysed, the auxiliary space complexity is O(1)

Therefore, the total space complexity is the sum of input space and auxiliary space: O(n)+O(1)=O(n)


This is extremely slow and not feasible within typical time limits (usually 1-2 seconds). Most programming environments allow around 10^8 operations per second, so 10^15 operations would take about 10 million seconds (over 115 days!), which is far too long.
The interviewer won’t be happy with your solution. 
We have to optimize the Time Complexity to move further in the interview!

Optimized Approach (Sliding Window)

Intuition

The key observation is that we don’t need to recalculate the sum from scratch every time we add a new number. If we’ve already checked a sequence of numbers, we can reuse that information and just adjust it slightly as we go along.

In the brute-force method, we are recalculating sums for overlapping parts of the array. For example, if we are traversing an array [2,3,1,2,4],, when you move from subarray [2, 3, 1, 2] to [3, 1, 2, 4], you’re recalculating the sum from scratch, even though three of the elements (3, 1, and 2) are the same.

The repeated calculations become a big problem when the array gets longer because you’re recalculating a lot of values that haven’t changed.

This observation suggests that if we could somehow reuse the sum from previous calculations rather than starting from scratch each time, we could speed things up.

Confused on what was re-calculated ?

target = 7 and nums = [2, 3, 1, 2, 4, 3], you would start by looking at each subarray like this:

Check [2], sum = 2 (not enough)
Check [2, 3], sum = 5 (2 was re-calculated)
Check [2, 3, 1], sum = 6 (2,3 were re-calculated)
Check [2, 3, 1, 2], sum = 8 (2, 3, 1 were re-calculated)

And so on, until you’d exhaust all possible subarrays. This would eventually give you the answer, but it would involve a lot of repeated and unnecessary calculations.

Can we visualize a frame in which it contains a series of numbers?
This frame is dynamic, Let's call this frame a "window" that shrinks and expands, and since the window shrinks and expands or slides over the array, we just call it the sliding window. Which means it can shrink and expand accordingly.
We can use this frame to optimize the solution.

Let’s imagine a way to keep track of a "frame" of numbers instead of recalculating each time.

  1. The frame will have two ends, the left end and the right end. When the window expands, the right end moves right. When the window shrinks, the left end moves right.
  2. Expand the frame until the sum of the numbers in the frame reaches or exceeds the target.
  3. Once you hit the target, shrink the frame from the left to see if you can get a smaller valid frame.
  4. Continue adjusting the frame by moving its left and right as needed, and keep track of the smallest frame that meets the target.

Let's call this frame a "window" that shrinks and expands and since the window shrinks and expands or slides over the array we just call it as the sliding window.

Points to Remember

Whenever we are expanding the window, we will add the right of the rightmost element to the sum.
Whenever we are shrinking the window, we will subtract the leftmost element from the sum.

Confused on the Algorithm ?

target = 7 and nums = [2, 3, 1, 2, 4, 3].
Start with an empty window: Begin with both the left and right pointers at the start of the array. Keep a curr variable to store the sum of the current window.

Expand the window by moving right to the right, adding each element nums[right] to curr.

Right = 0: Add nums[0] = 2 to curr, so curr = 2.
Right = 1: Add nums[1] = 3 to curr, so curr = 5.
Right = 2: Add nums[2] = 1 to curr, so curr = 6.
Right = 3: Add nums[3] = 2 to curr, so curr = 8. (Now curr ≥ target)

Shrink the window:
We reached our target, so we check the length: it’s right - left + 1 = 4.
Now try to shrink the window from the left to see if we can get a smaller subarray that still meets the target.
Remove nums[0] = 2 from curr, making curr = 6. Move left to 1.
Since curr is now less than the target, we stop shrinking and go back to expanding by moving right.
Continue expanding and shrinking:

Move right to 4: Add nums[4] = 4, making curr = 10.
Check window length (it’s 4, so no improvement).
Shrink again by moving left: remove nums[1] = 3 to get curr = 7 with length 3. Update minLen to 3.
End: Repeat this until right reaches the end of the array. The smallest valid subarray length found during this process is the answer.

How To Approach This Problem

Initialize Variables:Set a variable to store the minimum length of the subarray that meets the condition. Initially, set this to a large value, representing that we haven’t found a valid subarray yet.Set a pointer to mark the beginning of the window.Set a variable to keep track of the current sum of the elements within the window.

Expand the Window:Iterate over the elements in the array with a pointer representing the end of the window.For each element, add its value to the current sum. This expands the window to include the new element.

Check and Shrink the Window:While the current sum meets or exceeds the required condition, check the length of the current window. If it’s smaller than the minimum length recorded, update the minimum length.Then, shrink the window from the left by subtracting the value of the element at the start of the window from the current sum and moving the start pointer to the right. This reduces the window size while still meeting the required condition (if possible).

Return the Result:After iterating through the array, if a valid subarray was found, return its length. If not, return 0, as no subarray met the condition.

Let's visualize with a Video

0:00
/1:36

Dry-Run

nums[] = { 4 , 2 , 3 , 6 , 1 , 2 , 7 }
target= 9
Answer:- 2
Explantion:- The subarray [2,7] or [3,6] has sum 9 of size 2.

Initialize Variables
minLen = Infinity (We want the smallest subarray length that meets the condition)
left = 0 (Starting index of the window)
sum= 0 (Current sum of the elements within the window)

Expand the Window
We’ll use a for loop with right as the end of the window.
Iteration 1: right = 0
Add nums[0] = 4 to sum: sum= 4.
sum < target, so we continue expanding.

Iteration 2: right = 1
Add nums[1] = 2 to sum: sum = 6.
sum< target, so we continue expanding.

Iteration 3: right = 2
Add nums[2] = 3 to sum: sum = 9.
Now sum >= target, so we check the window size:
Current window size = right - left + 1 = 2 - 0 + 1 = 3.
Update minLen to 3.
To try finding a smaller valid window, we shrink from the left:
Subtract nums[left] = 4 from sum: sum = 5.
Move left to 1.

Iteration 4: right = 3
Add nums[3] = 6 to sum: sum = 11.
sum >= target, so we check the window size:
Current window size = right - left + 1 = 3.
minLen remains 3.
Shrink from the left:
Subtract nums[left] = 2 from curr: curr = 9.
Move left to 2.
Check again since sum >= target:
Window size = right - left + 1 = 2.
Update minLen to 2.
Shrink from the left:
Subtract nums[left] = 3 from sum: sum = 6.
Move left to 3.

Iteration 5: right = 4
Add nums[4] = 1 to sum: sum = 7.
sum< target, so continue expanding.
Iteration 6: right = 5
Add nums[5] = 2 to sum: sum= 9.
sum >= target, so we check the window size:
Window size = right - left + 1 = 3.
minLen remains 2.
Shrink from the left:
Subtract nums[left] = 6 from sum: sum = 3.
Move left to 4.

Iteration 7: right = 6
Add nums[6] = 7 to sum: sum= 10.
sum>= target, so we check the window size:
Window size = right - left + 1 = 3.
minLen remains 2.
Shrink from the left:
Subtract nums[left] = 1 from sum: sum= 9.
Move left to 5.
Check again since sum>= target:
Window size = right - left + 1 = 2.
minLen remains 2.
Shrink from the left:
Subtract nums[left] = 2 from sum: sum = 7.
Move left to 6.

Result
After finishing all iterations, the smallest subarray length minLen that meets the condition is 2. The subarrays [3, 6] and [2, 7] both have a sum of 9, achieving the target.

Final Output: minLen = 2

Optimal Code in all Languages
1. C++ Try on Compiler
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int minLength = INT_MAX;

        // Left pointer to track the start of the window
        int left = 0;

        // Variable to hold the current sum within the window
        int currentSum = 0;

        // Loop through each element with the right pointer
        for (int right = 0; right < nums.size(); right++) {
            // Add the current element to the current sum
            currentSum += nums[right];

            // While current sum meets or exceeds the target
            while (currentSum >= target) {
                // Update minimum length to the smaller of current or previous minimum length
                minLength = min(minLength, right - left + 1);

                // Shrink the window from the left
                currentSum -= nums[left];
                left++;
            }
        }

        // If no valid subarray was found, return 0
        return minLength == INT_MAX ? 0 : minLength;
    }
};

2. Java Try on Compiler
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        // Initialize minimum length to a large value
        int minLength = Integer.MAX_VALUE;

        // Left pointer to track the start of the window
        int left = 0;

        // Variable to hold the current sum within the window
        int currentSum = 0;

        // Right pointer to expand the window
        for (int right = 0; right < nums.length; right++) {
            // Add the current element to the current sum
            currentSum += nums[right];

            // While the current sum meets or exceeds the target
            while (currentSum >= target) {
                // Update minimum length if current window is smaller
                minLength = Math.min(minLength, right - left + 1);

                // Shrink the window from the left
                currentSum -= nums[left];
                left++;
            }
        }

        // If no valid subarray was found, return 0
        return minLength == Integer.MAX_VALUE ? 0 : minLength;
    }
}

3. Python Try on Compiler
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        # Initialize minimum length to a large value
        min_length = float('inf')

        # Left pointer to track the start of the window
        left = 0

        # Variable to hold the current sum within the window
        current_sum = 0

        # Loop through each element with the right pointer
        for right in range(len(nums)):
            # Add the current element to the current sum
            current_sum += nums[right]

            # While the current sum meets or exceeds the target
            while current_sum >= target:
                # Update minimum length to the smaller of current or previous minimum length
                min_length = min(min_length, right - left + 1)

                # Shrink the window from the left
                current_sum -= nums[left]
                left += 1

        # If no valid subarray was found, return 0
        return 0 if min_length == float('inf') else min_length

4. JavaScript Try on Compiler
/**
 * @param {number} target
 * @param {number[]} nums
 * @return {number}
 */
var minSubArrayLen = function(target, nums) {
    let minLength = Infinity;

    // Left pointer to track the start of the window
    let left = 0;

    // Variable to hold the current sum within the window
    let currentSum = 0;

    // Loop through each element with the right pointer
    for (let right = 0; right < nums.length; right++) {
        // Add the current element to the current sum
        currentSum += nums[right];

        // While the current sum meets or exceeds the target
        while (currentSum >= target) {
            // Update minimum length to the smaller of current or previous minimum length
            minLength = Math.min(minLength, right - left + 1);

            // Shrink the window from the left
            currentSum -= nums[left];
            left++;
        }
    }

    // If no valid subarray was found, return 0
    return minLength === Infinity ? 0 : minLength;
};

Time Complexity: O(n)

Since, both the left pointer will traverse the array once in the worst case. So, it's time complexity becomes O(n).
The right pointer will traverse till the end of the array which will result in O(n) time.

Total Time Complexity: Combining the above time complexities, the overall time complexity becomes O(n) + O(n) = O(2n) = O(n).

Space Complexity: O(n)

Auxiliary Space Complexity
Auxiliary space complexity refers to the extra space or temporary space used by an algorithm, excluding the input data. In this solution:

  • The auxiliary space is O(1) because it only uses a fixed number of variables (minLength, left, currentSum, etc.) regardless of the size of the input array nums.
  • This means that as the input size grows, the space used by these variables remains constant and does not depend on n.

Total Space Complexity
Total space complexity includes both the space used for the input data and the auxiliary space.

  • In this problem, the input array nums itself occupies O(n) space since it contains n elements.
  • When we combine this with the O(1) auxiliary space, the total space complexity remains O(n) , as the input array's size dominates.

  1. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit
  2. Longest Repeating Character Replacement
  3. Max Consecutive Ones III
  4. Substrings of Size Three with Distinct Characters

Given two strings s and t of lengths m and n respectively, return the minimum window

substring of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string "".

The testcases will be generated such that the answer is unique.

You are given an array of integers nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.

Return the max sliding window.

💡
Showcase your skills by joining LearnYard Technologies FZ-LLC as a Technical Content Writer. Apply now and inspire the next generation of learners—fill out the form: https://forms.gle/CGDsbGkcapSfvXKM8