53. 最大子序和
题目描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
解题思路
1. 动态规划
d
p
[
i
]
dp[i]
dp[i] 表示前
i
+
1
i+1
i+1个元素所组成的连续子数组的最大和。
初始状态注意:
d
p
[
0
]
=
n
u
m
s
[
0
]
dp[0] = nums[0]
dp[0]=nums[0]
如果
d
p
[
i
−
1
]
<
=
0
dp[i-1]<=0
dp[i−1]<=0(前一个元素对我们没有正的贡献)
d
p
[
i
]
=
n
u
m
s
[
i
]
dp[i] = nums[i]
dp[i]=nums[i],否则我们需要把正贡献加到后面去,也就是
d
p
[
i
]
=
d
p
[
i
−
1
]
+
n
u
m
s
[
i
]
dp[i] = dp[i-1] + nums[i]
dp[i]=dp[i−1]+nums[i]
最后返回max(dp)。
dp = [-float('inf')] * len(nums)
dp[0]=nums[0]
for i in range(1,len(nums)):
if dp[i-1] <= 0:
dp[i] = nums[i]
else:
dp[i] = dp[i-1]+nums[i]
return max(dp)
时间复杂度O(n)
2. 分治
- 切分终止条件:
直到锁所以问题的长度为1的数组,停止切分 - 大问题切分
递归地将原数组二分为左区间和右区间,直到最终的数组只剩下一个元素,将其返回 - 处理子问题得到子结果,合并结果
i. 左区间:从右到左计算最大子序和
ii. 右区间:从左到右计算最大子序和 - 合并之后就是整个区间的最大子序和
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
if n == 1:
return nums[0]
left = self.maxSubArray(nums[:len(nums)//2])
right = self.maxSubArray(nums[len(nums)//2:])
# 处理子问题
max_1 = nums[len(nums)//2-1]
tmp = 0
for i in range(len(nums)//2-1,-1,-1):
tmp += nums[i]
max_1 = max(tmp,max_1)
# 从左到右计算最大子序和
max_r = nums[len(nums)//2]
tmp = 0
for i in range(len(nums)//2,len(nums)):
tmp += nums[i]
max_r = max(tmp,max_r)
return max(left,right,max_1+max_r)
reference
[1]53. 最大子序和https://leetcode-cn.com/problems/maximum-subarray/submissions/