题目描述:
Given an integer array nums
, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6
题目分析:
该题属于Array类别,通过贪心可以实现O(n)级别的解决思路,通过分治法可以实现O(nlogn)的解决思路。
贪心法O(n)解决思路:
对于序列[A1,A2,...,AN]的遍历中,我们要求序列AI+...+AJ的和最大。
贪心算法在该问题的应用体现在我们在对序列遍历(i)求和的过程中,同时比较序列A0,...Ai的和与Ai的大小关系,两者的max值作为遍历至i时刻的当前序列最大sum.
并将当前序列最大sum与实际最大值比较,当序列遍历完毕,我们则求得整个序列的最大子集和。
Runtime: 72 ms, faster than 91.17% of Python3 online submissions for Maximum Subarray.
Memory Usage: 14.6 MB, less than 5.02% of Python3 online submissions for Maximum Subarray.
length = len(nums)
summax = nums[0]
cummax = nums[0]
for num in nums[1:]:
cummax = cummax+num
if cummax <num:
cummax = num
if cummax >summax:
summax = cummax
return summax
分治法O(nlogn)解决思路:
分治算法一般实现分为三个步骤:
(1)划分问题:将问题的实例划分为子问题,在本题中,就是将长度为l的序列不断划分为l/2的序列问题;
如划分中点m = l +int((r-l)/2)
在这里,需要注意区间的划分问题,在本题中,我采用较常用的左闭右开的区间划分方式,这样子在处理数组分割的问题比较自然。
对于一个长度为L的数组问题,我们视为区间[0,L),在第一次递归分治的划分过程中,分成[0,m) [m,L)
区间划分问题决定了我们如何确定递归终止条件
如划分为左闭右开:
对于任何长度大于等于2的数组,我们的递归终止条件为left-right==1
对于长度为1的数组,我们直接设定递归终止条件为left==right
(2)递归求解:递归解决子问题,在本题中,通过递归调用maxsub(left,m) maxsub(right,m),求得左右各子区间的最大序列sum值。递归终止条件在(1)中已提;
(3)合并问题:在(2)中我们已求得左右各子区间的最大序列sum值,接下来我们要考虑:左右子区间之间是否存在更大的序列sum值。
则我们需要从当前中点m为起点,向左遍历至left,求得最大的leftsummax
向右遍历至right-1,求得最大的rightsummax,
在将leftsummax+rightsummax与(2)中的最大值比较,作为当前递归的最后结果。
如果leftsummax+rightsummax大于(2)中的最大值,则说明左右子区间,包含中间m点在内的子序列存在更大的序列sum值
Runtime: 164 ms, faster than 5.83% of Python3 online submissions for Maximum Subarray.
Memory Usage: 14.8 MB, less than 5.02% of Python3 online submissions for Maximum Subarray.
class Solution:
def maxsubhelper(self,nums,l,r):
if r-l==1:
return nums[l]
if r==l:
return nums[l]
m = l + int((r-l)/2)
maxtmp = max(self.maxsubhelper(nums,l,m),self.maxsubhelper(nums,m,r))
leftmax=0
leftsummax = nums[m-1]
for i in range(m-1,l-1,-1):
leftmax += nums[i]
leftsummax = max(leftsummax,leftmax)
rightmax = 0
rightsummax = nums[m]
for i in range(m,r):
rightmax += nums[i]
rightsummax = max (rightsummax,rightmax)
return max(maxtmp,leftsummax+rightsummax)
def maxSubArray(self, nums: List[int]) -> int:
return self.maxsubhelper(nums,0,len(nums))