给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
一道标准的动态规划题。设置一个dp一维列表存放每前进一步时的最优解(本题中就是和),初始的dp[0]为nums的第一个值。dp列表的取值就是,当前这一步加上之前最优值、当前值中的最大值。不断循环至最后一个元素。最后找dp中的最大值。代码一次通过:
class Solution:
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 0:
return 0
elif len(nums) == 1:
return nums[0]
dp = list(range(len(nums)))
dp[0] = nums[0]
for i in range(1, len(nums)):
dp[i] = max((dp[i-1] + nums[i]), nums[i])
return max(dp)
其实还想到一个问题,就是问到从哪里开始的这个最优子列表。想法是设置一个flag列表,每次使用自身值作为dp元素值时,把坐标给flag存进去。最后的最优求和值,对应着一个下标,这个下标正是最优子列表的结尾下标;而它之前的最后一个flag的存档,必然是最优子列表的其实下标。
分治算法没有尝试,看了网上的做法能理解大概意思。转一个分治算法过来:
class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
sum = 0
l = len(nums)
if l == 1:
return nums[0]
left = self.maxSubArray(nums[:l//2])
right = self.maxSubArray(nums[l//2:])
s1 = nums[(l//2)-1]
lsum = 0
for i in nums[:l//2][::-1]:
lsum += i
if lsum > s1:
s1 = lsum
s2 = nums[l//2]
rsum=0
for j in nums[l//2:]:
rsum += j
if rsum > s2:
s2 = rsum
sum = s1+s2
if sum<left:
sum = left
if sum<right:
sum = right
return sum
That's all!