力扣053 最大子序和
题干
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解析
子序和这个问题研一考算法的时候考过,所以有印象是考察动态规划(DP)的题目,所以也就往那方面思考了,数组作为一个线性结构,解本题也是用不到二维数组的,用一维数组就足够了。
我们可以构造一个新数组results,长度和原数组nums相同,results中各元素代表当前索引下的最大子序和。
DP的一个关键思想就是找出当前值与前序值之间的关系,这里results[i]和results[i-1]之间的关系取决于nums[i],取决于我们是否将nums[i]加入子序中,可以这样想,我们对nums[i]的处理无非两种:
1、将nums[i]合并到前序子序中,此时子序和为 results[i-1]+nums[i]
2、不将nums[i]合并到前序子序中,此时nums[i]作为新子序的开头,子序和即为nums[i]本身。
那么再看一下这两种选择下,分别会带来怎样的最大子序和:
1、results[i-1]+nums[i]
2、nums[i]
results[i]的值只会是这两种之一,具体是哪一种,由于题干要求的是最大子序和,所以选择两者中较大的即可,再简化一下的话,观察这两个值,只要判断results[i-1]是正是负即可。
上面有个地方之所以加粗是因为,我最开始这一段没想清楚,我当时想的是,如果nums[i]带来的是负收益,那么此时results[i]的值就是0。但这是错的,因为如果不将nums[i]加入前序子序,那么nums[i]自身就是下一个子序的开头。
代码
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
results = [nums[0]]
for i in range(1, len(nums)):
results.append(results[i-1]+nums[i] if results[i-1] >= 0 else nums[i])
return max(results)
这里有一个注意点就是,我们遍历是从索引1开始的,因为需要和前序做比较,所以索引0是没有前序的。且索引0的最大子序和即为nums[0]本身。