标签:
Problem Difinition:
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
.
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
Solution:
1)动态规划.
输入数组为nums,用 a[i] 表示nums[0...i]这部分元素的子序列(此子序列以元素nums[i]结尾,不管它以谁开头)能得到的最大累加和。则有递推关系:
a[ i ] =nums[ i ]+ ( a[i-1] if a[i-1]>0 else 0)
求解过程就是迭代整个数组,求最大的a[ i ]。可以用一个数组来保存所有的a[ i ],空间复杂度O(n)。
然而实际上不需要一个数组来存放所有的a[ i ],而用一个变量代替。
1 # @param {integer[]} nums 2 # @return {integer} 3 def maxSubArray(nums): 4 5 maxSum=-sys.maxint 6 sm=0 7 begin=0 8 end=0 9 maxBegin=0 10 maxEnd=0 11 for i, n in enumerate(nums): 12 sm+=n 13 if sm>maxSum: 14 maxSum=sm 15 maxBegin=begin 16 maxEnd=end 17 if sm<=0: 18 begin=i+1 19 end=i+1 20 sm=0 21 else: 22 end+=1 23 return nums[maxBegin: maxEnd+1]
以上算法会求出得到最大和的完整子序列,更通用,思路也表达得比较清晰。然而题目的要求只是求出这个最大和,所以可以精简很多:
1 # @param {integer[]} nums 2 # @return {integer} 3 def maxSubArray(nums): 4 maxSum=-sys.maxint 5 sm=0 6 for n in nums: 7 sm+=n 8 maxSum=max(maxSum, sm) 9 sm=max(sm, 0) 10 return maxSum
实际上想法很简单,逐一累加元素,一旦和不大于0,则从下一个位置开始,重新累加,并在这个过程中不断更新最大和。
2)分治。
基本思想:
1._分。把数组切成左右两部分,那么给出最大累加和的子序列,要么全在左边,要么全在右边,要么就横跨左右两边(子序列包含了中间元素)
2._合。整个数组的最大累加和就是max(左边的最大和, 右边的最大和, 跨越两边的最大和)
于是可以:a.先分别求左右两个部分的最大累加和,这是一个递归的过程;
b.求跨越左右两边的子序列能够给出的最大累加和;
c.返回三个和中的最大值,作为整个序列的最大累加和。
关键是b.过程。其实也很简单,以中间元素为起点,分别向左右两边扩展,求出在左边子序列中,后缀序列能达到的最大累加和;以及
右边序列中,前缀序列能达到的最大累加和,这俩累加和加起来即可。
设中间节点的下标为m,那所谓的左边子序列的后缀就是:nums[...m-2, m-1, m],右边子序列的前缀就是nums[m+1, m+2...].
1 # @param {integer[]} nums 2 # @return {integer} 3 def maxSubArray(self, nums): 4 if len(nums)==0: 5 return 0 6 return self.recur(nums, 0, len(nums)-1) 7 8 9 def recur(self, nums, start, end): 10 if start==end: #one element 11 return nums[start] 12 mid=(start+end)/2 13 leftAns=self.recur(nums, start, mid) 14 rightAns=self.recur(nums, mid+1, end) 15 leftMax=nums[mid] 16 rightMax=nums[mid+1] 17 tmp=0 18 for i in range(mid, start-1, -1): #直接加到最后吧 19 tmp+=nums[i] 20 leftMax=max(leftMax, tmp) 21 tmp=0 22 for i in range(mid+1, end+1): 23 tmp+=nums[i] 24 rightMax=max(rightMax, tmp) 25 return max(leftAns, rightAns, leftMax+rightMax)
标签:
原文地址:http://www.cnblogs.com/acetseng/p/4703378.html