# 解法一 穷举 i 表示取数组中元素的个数, j表示数组开始的位置# 此解法由于枚举效率过低 超出时间限制classSolution:defmaxSubArray(self, nums)->int:ifnot nums:returnNone
lmax, larr =-9e32,len(nums)for i inrange(1, larr +1):
j =0while i + j <= larr:
tmp =sum(nums[j: i + j])
lmax = tmp if tmp > lmax else lmax
j +=1return lmax
# 解法二 动态规划 arr[i]表示 以数组中第i个元素为终点的最大子序和# 半成品 仍然可以优化classSolution:defmaxSubArray(self, nums)->int:ifnot nums:returnNone
pre, cur, res =-1e32,None,-1e32for i, val inenumerate(nums):
cur = val if val > pre + val else pre + val
pre, res = cur, res if res > cur else cur
return res
# 优化版一 经过测试发现enumarate效率较低classSolution:defmaxSubArray(self, nums)->int:ifnot nums:returnNone
pre_max = ret = nums[0]
nums = nums[1:]# 这一行代码可以使测试用例节约内存至少300m 相较于循环处切片方法for i in nums:
pre_max = i if i > i + pre_max else i + pre_max
ret = ret if ret > pre_max else pre_max
return ret
# 优化版二 使用列表的__len__()函数获取列表元素长度,通过索引操作数组避免切片 可以减少内存占用classSolution:defmaxSubArray(self, nums)->int:ifnot nums:returnNonedefget_max(nums, st, end):
pre_max = ret = nums[0]for i inrange(st, end):
pre_max = nums[i]if nums[i]> nums[i]+ pre_max else nums[i]+ pre_max
ret = ret if ret > pre_max else pre_max
return ret
return get_max(nums,1, nums.__len__())
# 分治策略# 最大值可能在数组左边 可能在数组右边 可能跨越数组中央# 跨越中央时需计算最大前缀和最大后缀defmaxSubArray(nums, start, end):ifnot nums:returnNoneif start == end:return nums[start]
mid =(start + end)//2
left = maxSubArray(nums, start, mid)# 左边最大值
right = maxSubArray(nums, mid +1, end)# 右边最大值
pre, post = nums[mid], nums[mid +1]# pre前缀 post后缀
max_pre_post = pre
for i inrange(mid -1, start -1,-1):
pre += nums[i]
max_pre_post = max_pre_post if max_pre_post > pre else pre
pre, max_pre_post = max_pre_post, post
for i inrange(mid +2, end +1):
post += nums[i]
max_pre_post = max_pre_post if max_pre_post > post else post
post = max_pre_post
returnmax(left, right, pre + post)# 最大值即为 左中右中最大的