leetcode 每日一题 53. 最大子序和
动态规划
思路:
由于题目只要求得到最大和,故可以遍历数组nums,遍历的同时把每个元素的值更新为当前位置到之前所能得到的最大和,遍历完成后返回数组中最大值即可。更新的动态规划转移方程为:nums[i] = nums[i] + max(nums[i-1],0)
代码:
class Solution: def maxSubArray(self, nums: List[int]) -> int: for i in range(1, len(nums)): nums[i]= nums[i] + max(nums[i-1], 0) return max(nums)
分治法
思路:
对于区间 [ l , r ] ,要获得区间内最大子段和,令m = (l+r)/2,我们可以把区间分为 [ l , m ] 和 [ m+1 , r ] 进行分治求解。
对于一个区间 [ l , r ] :
- lSum表示 [ l , r ] 以 l 为左端点的最大字段和
- rSum表示 [ l , r ] 以 r 为右端点的最大字段和
- mSum表示 [ l , r ] 最大字段和
- iSum表示 [ l , r ] 区间和
这里我们要找到区间Q [ l , r ] 这四个字段和两个子数组q1 [ l , m ] ,q2 [ m+1 ,r] 之间的关系。
Q.ISum = max(q1.lSum,q1.iSum+q2.lSum)
Q.rSum = max(q2.rSum,q2.iSum+q1.rSum)
Q.mSum = max(max(q1.mSum,q2.mSum),q1.rSum+q2.lSum)
Q.iSum = q1.iSum+q2.iSum
对2个子区间继续进行拆分,直到区间只剩下一个元素,这个时候区间四个值均等于这个元素,接着按照上面关系,两两回升合并,得到最后答案。
代码:
class Section: def __init__(self,lSum,rSum,iSum,mSum): self.lSum = lSum self.rSum = rSum self.iSum = iSum self.mSum = mSum class Solution: def pushUp(self,lSub,rSub): iSum = lSub.iSum + rSub.iSum lSum = max(lSub.lSum,lSub.iSum+rSub.lSum) rSum = max(rSub.rSum,rSub.iSum+lSub.rSum) mSum = max(max(lSub.mSum,rSub.mSum),lSub.rSum+rSub.lSum) return Section(lSum,rSum,iSum,mSum) def getSection(self,nums,l,r): if l == r: return Section(nums[l],nums[l],nums[l],nums[l]) m = (l+r)//2 lSub = self.getSection(nums,l,m) rSub = self.getSection(nums,m+1,r) return self.pushUp(lSub,rSub) def maxSubArray(self, nums: List[int]) -> int: return self.getSection(nums,0,len(nums)-1).mSum