Maximum Subarray II

Question

Given an array of integers, find two non-overlapping subarrays which have the largest sum.

The number in each subarray should be contiguous.

Return the largest sum.

Example For given [1, 3, -1, 2, -1, 2], the two subarrays are [1, 3] and [2, -1, 2] or [1, 3, -1, 2] and [2], they both have the largest sum 7.

Note The subarray should contain at least one number

Challenge Can you do it in time complexity O(n) ?

Analysis

  • 一个number

注意点

  • non-overlapping

Thoughts

这一题有点像buy stock III, 分割两边然后再求最大值的做法,所以采取类似的做法

如果采取maximum subarray的办法去求每一个index的两边,则需要 O(n^2)

这里才去和buy stock III类似的题目,但是略有不同 对于左边,用两个array left[]leftMax[] left[i]表示以i为end的subarray的maximum sum leftMax[i]表示在[0:i]区间内的subarray的maximum sum (不一定以nums[i]为end)

右边同理,剩下的同buy stock iii

Solution

O(n^2)做法

class Solution:
    """
    @param nums: A list of integers
    @return: An integer denotes the sum of max two non-overlapping subarrays
    """
    def maxTwoSubArrays(self, nums):
        # write your code here    
        if not nums:
            return 0

        length = len(nums)    

        left = [0 for i in range(length)]    
        right = [0 for i in range(length)]   

        #at least one number, so stop at the last 2th element
        #left part include current element
        for i in range(length-1):
            leftPart = nums[:i+1]
            rightPart = nums[i+1:]
            left[i] = self.maxSubArray(leftPart)
            right[i] = self.maxSubArray(rightPart)

        #start calcuate for each index
        maxSum = sys.maxint * -1
        for i in range(length-1):
            currentSum = left[i] + right[i]
            if currentSum > maxSum:
                maxSum = currentSum
        return maxSum

    def maxSubArray(self, nums):
        # write your code here
        if not nums:
            return 0
        currentSum = nums[0]
        length = len(nums)
        if length == 1:
            return nums[0]
        maxSum = sys.maxint * -1
        for i in range(1, length):
            if currentSum < 0:
                currentSum = nums[i]
            else:
                currentSum += nums[i]
            if maxSum < currentSum:
                maxSum = currentSum
        return maxSum

O(n)做法

class Solution:
    """
    @param nums: A list of integers
    @return: An integer denotes the sum of max two non-overlapping subarrays
    """
    def maxTwoSubArrays(self, nums):
        # write your code here    
        if not nums:
            return 0

        length = len(nums)

        left = [0 for i in range(length)]
        leftMax = [ 0 for i in range(length)]
        right = [0 for i in range(length)]
        rightMax = [ 0 for i in range(length)]

        left[0] = nums[0]
        leftMax[0] = nums[0]
        for i in range(1, length):
            if left[i-1] < 0:
                left[i] = nums[i]
            else:
                left[i] = left[i-1] + nums[i]
            leftMax[i] = max(left[i], leftMax[i-1])

        right[length-1] = sys.maxint * -1
        rightMax[length-1] = sys.maxint * -1

        for i in range(length-2, -1, -1):
            if right[i+1] < 0:
                right[i] = nums[i+1]
            else:
                right[i] = right[i+1] + nums[i+1]
            rightMax[i] = max(right[i], rightMax[i+1])

        #start calcuate for each index
        maxSum = sys.maxint * -1
        for i in range(length-1):
            currentSum = leftMax[i] + rightMax[i]
            if currentSum > maxSum:
                maxSum = currentSum
        return maxSum