Leetcode 209: Minimum Size Subarray Sum

The original question can be found here.

The question is asking us to the minimum length of subarray that it’s sum is no less than target value.

Brute Force

The brute force we can immediately think of is to enumerate all subarrays and keep track of the minimum length.

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        min_length = float('inf')
        for i in range(0, len(nums)):
            sum = 0
            for j in range(i, len(nums)):
                sum += nums[j]
                if sum >= target:
                    min_length = min(min_length, j - i + 1)
                    break
        
        return 0 if min_length == float('inf') else min_length

Time Complexity: O(n^2). Space Complexity: O(1).

Binary Search

You may ask: this array is not sorted, why can we use binary search? Well, though the array is not sorted, but the prefix sum is sorted since all the numbers in array are positive. If you’re not familiar with prefix sum, please look at my another post here.

nums:      [2, 3, 1, 2, 4, 3]          target: 7
prefix: [0, 2, 5, 6, 8, 12, 15]

For each prefix sum x, we try to find the smallest y that y - x >= 7. A standard binary search question, right?

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        min_length, sum = float('inf'), 0
        prefix_sum = [sum]
        
        for num in nums:
            sum += num
            prefix_sum.append(sum)

        for index, element in enumerate(prefix_sum):
            the_other_index = self.binary_search(prefix_sum, index + 1, target + element)
            if the_other_index != -1:
                min_length = min(min_length, the_other_index - index)
            
        return 0 if min_length == float('inf') else min_length
        
    def binary_search(self, sums: List[int], start_index: int, target: int) -> int:
        if start_index >= len(sums):
            return -1
        
        left, right = start_index, len(sums) - 1
        while left + 1 < right:
            mid = (left + right) // 2
            if sums[mid] < target:
                left = mid
            else:
                right = mid

        if sums[left] >= target:
            return left
        
        if sums[right] >= target:
            return right

        return -1

Time Complexity: O(nlgn). Space Complexity: O(n).

2 Pointers

We maintain a sliding window, and make sure the window always have just enough elements that their sum is no less than target. To achieve this, we first expand the right pointer until the sum of elements inside sliding window is no less than target. Then we shrink the left pointer and make sure the sum in sliding window is still no less than target.

class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left, right = 0, 0
        min_length = float('inf')
        sum = nums[0]

        while left < len(nums):
            while sum < target and right + 1 < len(nums):
                right += 1
                sum += nums[right]
            if sum < target:
                break
            while sum >= target:
                min_length = min(min_length, right - left + 1)
                sum -= nums[left]
                left += 1

        return 0 if min_length == float('inf') else min_length

Time Complexity: O(n). Space Complexity: O(1).

Scroll to Top