题目描述
https://leetcode-cn.com/problems/maximum-subarray/
思路题解
1.动态规划(需额外开辟数组)
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
dp=[nums[0]]
for i in range(1,len(nums)):
dp.append(max(dp[i-1]+nums[i],nums[i]))
return max(dp)
2.动态规划(不需额外开辟数组)
go代码
func maxSubArray(nums []int) int {
ans:=nums[0]
for i:=1;i<len(nums);i++{
if nums[i]<nums[i]+nums[i-1]{
nums[i]=nums[i]+nums[i-1]
ans=max(ans,nums[i])
}else{
ans=max(ans,nums[i])
}
}
return ans
}
func max(i,j int)int{
if i>j{return i}else {return j}
}
python3代码
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
ans=nums[0]
for i in range(1,len(nums)):
nums[i]=max(nums[i-1]+nums[i],nums[i])
ans=max(ans,nums[i])
return ans
3.分治法
分治法,最大子序和的分布分三种情况:
- 在左半部分
- 在右半部分
- 横跨两部分(即包括左半部分的最后一个元素,和右半部分的第一个元素
最后,返回这三种情况的最大值即可,总的时间复杂度O(nlogn)。
注意:第三种情况,以计算右半部分为例,因为必须以右边第一个元素为起点,因此不存在判断加上此节点nums[i]
和不加此节点的最大值的情况(即不需要leftBorderSum =max(leftBorderSum+nums[i],nums[i])
),直接让leftBorderSum =max(leftBorderSum, leftSum)
即可。
class Solution(object):
def maxSubArray(self, nums):
#左右边界
left = 0
right = len(nums)-1
#求最大和的值
maxSum = self.divide(nums,left,right)
return maxSum
def divide(self,nums,left,right):
#递归出口:如果只有一个元素就返回这个元素
if left==right:
return nums[left]
#求中心点
center = (left+right)//2
#1.求子序在中心点左边的和
leftMaxSum = self.divide(nums,left,center)
#2.求子序在中心点右边的和
rightMaxSum = self.divide(nums,center+1,right)
#3.求子序横跨2边的和,分成左边界和和右边界和
leftBorderSum = nums[center]
leftSum = nums[center]
for i in range(center-1,left-1,-1):
leftSum += nums[i]
leftBorderSum =max(leftBorderSum, leftSum)
rightBorderSum = nums[center+1]
rightSum = nums[center+1]
for i in range(center+2,right+1):
rightSum += nums[i]
rightBorderSum =max(rightBorderSum, rightSum)
#左边界的和 + 右边那块的和
BorderSum = leftBorderSum + rightBorderSum
return max(leftMaxSum,rightMaxSum,BorderSum)