目录
53. 最大子序和
https://leetcode-cn.com/problems/maximum-subarray/
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:输入: [-2,1,-3,4,-1,2,1,-5,4]、输出: 6、解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
题解
一:贪心?其实感觉类似法二,当累加和小于0,抛弃前面的累加和,因为将其加到当前的值上,不能提升以当前值结尾的和。
class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
if n == 0:
return 0
ans = nums[0]
local_sum = nums[0]
for i in range(1, n):
if local_sum < 0:
local_sum = nums[i]
else:
local_sum += nums[i]
ans = max(ans, local_sum)
return max(ans, local_sum)
二:动态规划,local_sum是以nums[i]结尾的区间的最大和。
class Solution(object):
def maxSubArray(self, nums):
n = len(nums)
if n == 0:
return 0
ans = nums[0]
local_sum = nums[0]
for i in range(1, n):
local_sum = max(local_sum + nums[i], nums[i])
ans = max(local_sum, ans)
return ans
三:分治,渐进时间复杂度也是O(n)。例如l_sub = self.get(nums, l, mid)存储的是[l, mid]上,以l为左端点的最大和(l_sub.l_sum), 以r为右端点的最大和(l_sub.r_sum), [l, mid]上的最大和(l_sub.m_sum),[l,mid]上的区间和(l_sub.t_sum)。
class AllkindSum(object):
def __init__(self, l_sum, r_sum, m_sum, t_sum):
#[a, b]
self.l_sum = l_sum # 以区间左端点为左端点的最大和
self.r_sum = r_sum # 以区间右端点为右端点的最大和
self.m_sum = m_sum # 左右端点均不限制的最大和
self.t_sum = t_sum # 该区间的和
class Solution(object):
def push_up(self, l, r):
#l :[l, mid], r: [mid+1, r]
t_sum = l.t_sum + r.t_sum
l_sum = max(l.l_sum, l.t_sum + r.l_sum)
r_sum = max(r.r_sum, r.t_sum + l.r_sum)
m_sum = max([l.m_sum, r.m_sum, l.r_sum + r.l_sum])
return AllkindSum(l_sum, r_sum, m_sum, t_sum)
def get(self, nums, l, r):
if l == r:
return AllkindSum(nums[l], nums[l], nums[l], nums[l])
mid = l + (r - l) // 2
l_sub = self.get(nums, l, mid)
r_sub = self.get(nums, mid + 1, r)
return self.push_up(l_sub, r_sub)
def maxSubArray(self, nums):
return self.get(nums, 0, len(nums) - 1).m_sum