[53][简单][动态规划][分治] 最大子序和
题目描述
53. 最大子序和 剑指 Offer 42. 连续子数组的最大和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
解题思路
动态规划
用状态表示以第个数结尾的连续子数组的最大和, 显然最后的结果就是.
以第个数的角度考虑, 如果能与前一位连在一起, 要求前一位必须不小于0, 否则与前面相加会变小, 肯定不会是连续最大和对应子数组的一部分. 如果第个数是后续某个数连续最大和对应的子序列的一部分, 那肯定是不包含之前的部分.
因此对应的状态转移方程为:
得到一个时间复杂度为, 空间复杂度为的算法.
可以使用滚动数组思想, 进一步节省空间. 由于每一步只使用上一步的结果, 因此只要保存上一步的即可, 空间复杂度压缩为.
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
if n == 0:
return 0
a, total = -1e12, -1e12
for num in nums:
a = max(num + a, num)
total = max(a, total)
return total
分治
分治的思路参考解题思路: 最大子序和中的方法二.
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
n = len(nums)
if n == 0:
return 0
l, r, m, s = self.sub_array(nums, 0, n - 1)
return m
def sub_array(self, array, start, end):
if start == end:
t = array[start]
return t, t, t, t # left, right, max, sum
mid = (start + end) // 2
ll, lr, lm, ls = self.sub_array(array, start, mid)
rl, rr, rm, rs = self.sub_array(array, mid + 1, end)
l = max(ll, ls + rl)
r = max(rr, rs + lr)
m = max([lm, rm, lr + rl])
s = ls + rs
return l, r, m, s
最后更新于
这有帮助吗?