Minimum Size Subarray Sum

题目描述

Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn't one, return 0 instead.

For example, given the array [2,3,1,2,4,3] and s = 7, the subarray [4,3] has the minimal length under the problem constraint.

Challenge If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).

解题方法

首先要问清楚面试官,如果没有解应该返回什么,比如

  • [1,1], 3
  • [], 2 ....

two pointer

这道题可以用two pointer解,对每一个i,将j向右移,直到sum >= s, 后面的j就不用看了,因为都是positive,所以肯定大于s

time complexity: O(n) space complexity: O(1)

二分法

这种subarray sum的题目,很多都可以采取类似的方法: 用一个sums[], sums[i]表示nums[0:i]的sum,然后对于sums[i], 用二分法找到右边的边界,因为都是Positive number,所以sums必然是一个 递增sorted array.

Solution

class Solution(object):
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        length = len(nums)
        if length == 0:
            return 0
        p1, p2 = 0, 0
        currSum = 0
        minLen = sys.maxint
        while p1 < length:
            while currSum < s and p2 < length:
                currSum += nums[p2]
                p2 += 1
            #if currSum is larger than s, count the len
            #in case of the p2 >= length
            if currSum >= s:
                currLen = p2 - p1
                if minLen > currLen:
                    minLen = currLen
            currSum -= nums[p1]
            p1 += 1

        if minLen == sys.maxint:
            return 0
        else:
            return minLen

二分法

class Solution(object):
    def minSubArrayLen(self, s, nums):
        """
        :type s: int
        :type nums: List[int]
        :rtype: int
        """
        length = len(nums)
        if length == 0:
            return 0
        sums = [0 for i in range(length+1)]
        result = sys.maxint
        sums[1] = nums[0]
        for i in range(1, length+1):
            sums[i] = sums[i-1] + nums[i-1]

        for i in range(length):
            rightEnd = self.searchRight(i, length, sums[i] + s, sums)
            if rightEnd != length + 1:
                currLen = rightEnd - i
                if currLen < result:
                    result = currLen

        if result == sys.maxint:
            return 0
        else:
            return result

    def searchRight(self, start, end, target, sums):
        while start + 1 < end:
            mid = start + (end - start) / 2
            if sums[mid] >= target:
                end = mid
            else:
                start = mid
        if sums[start] >= target:
            return start
        if sums[end] >= target:
            return end
        return len(sums) + 1