leetcode.53.Maximum Subarray

来源:互联网 发布:北京我知科技公司 编辑:程序博客网 时间:2024/06/03 19:10

Description

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [-2,1,-3,4,-1,2,1,-5,4],
the contiguous subarray [4,-1,2,1] has the largest sum = 6.

sln1

将寻求输入数组nums的maximun subarray的问题,分解成求nums[:numsSize - 1]的maximun subarray和是nums[numsSize - 1]与nums[:numsSize - 1]的maximun subarray与nums的maximun subarray之间关系的问题。
假设我们已经知道了nums[:numsSize - 1]的maximun subarray,那么这个subarray有两种可能,分别是是否以nums[numsSize - 2]为最后一个元素。当maximun subarray是以nums[numsSize - 2]为最后一个元素的时候,那么nums[numsSize - 1]则有可能与nums[:numsSize - 1]的maximun subarray共同组成nums的maximun subarray。
因此,我们只需要记录,nums[:numsSize - 1]的maximun subarray以及其以最后一个元素为maximun subarray时,subarray的和为多少即可。
以下用max_ending_here记录当一个子集的maximun subarray必须包含最后一个元素时,这个maximun subarray的和。用max_so_far记录一个子集的maximun subarray的和。那么初始状态是,max_ending_here=max_so_far=nums[0]
代码如下:

class Solution(object):    def maxSubArray(self, nums):        """        :type nums: List[int]        :rtype: int        """        max_so_far = nums[0]        max_ending_here = nums[0]        for i in xrange(1, len(nums)):            max_ending_here = max(max_ending_here + nums[i], nums[i])            max_so_far = max(max_so_far, max_ending_here)        return max_so_far

sln2

用分治法的思想去解决这个问题,取输入数组的中间元素作为分隔元素,将输入数组分成nums[:k], nums[k]以及nums[k+1:n]。我们记left=nums[:k],right=nums[k+1:n],那么nums的maximun subarray则要不是left的maximun subarray,要不是right的maximun subarray,要不是一个包含nums[k]的subarray。那么我们只需要计算从nums[k]开始向左得到的最大subarray和以及向右计算得到的最大subarray和,并记为middle。最后,从left,middle和right选择一个最大的作为nums的maximun subarray和。代码如下

class Solution(object):    def maxSubArray(self, nums):        """        :type nums: List[int]        :rtype: int        """        return self.maxSubArray_divide(nums, 0, len(nums) - 1)    def maxSubArray_divide(self, nums, left, right):        if left == right:            return nums[left]        middle = (left + right) / 2        maxLeft = self.maxSubArray_divide(nums, left, middle)        maxRight = self.maxSubArray_divide(nums, middle + 1, right)        leftMaxSum = None        tmpSum = 0        for i in xrange(middle - left + 1):            tmpSum += nums[middle - i]            leftMaxSum = tmpSum if leftMaxSum is None or tmpSum > leftMaxSum else leftMaxSum        rightMaxSum = None        tmpSum = 0        for i in xrange(right - middle):            tmpSum += nums[middle + i + 1]            rightMaxSum = tmpSum if rightMaxSum is None or tmpSum > rightMaxSum else rightMaxSum        maxMiddle = max([leftMaxSum, rightMaxSum, leftMaxSum + rightMaxSum])        ret = max([maxLeft, maxRight, maxMiddle])        return ret
0 0