文章目录

  • ​​题目描述​​
  • ​​动态规划​​
  • ​​思路分析​​
  • ​​完整代码​​
  • ​​贪心:​​

题目描述

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。

示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:
输入:nums = [1]
输出:1

示例 3:
输入:nums = [5,4,-1,7,8]
输出:23

动态规划

思路分析

老规矩,动态规划五步走:

1.确定dp下标含义:

dp[i] 定义为以下标i为结束下标的子数组的最大和。

这里要注意:只是以i为结束下标,并不一定是以0为开始的。只要记住这里可能是0 到 i , 1 到 i , n到i,反正就是 不管是从哪里到i,dp[i] 就表示到下标i的子序列的最大和。

2.状态转移公式:

遍历到nums[i] 的时候,肯定是要这个值,因为我们dp的含义就是到这个值的,也就是从这个值之前的子数组的最大和。

在必须选择nums[i]的情况下:

  • dp[i-1] 是大于0的,那么这时候直接把nums[i] 加入就行
  • dp[i-1] 是小于等于0的,那么这时候就不要前面那些了,直接另起炉灶 dp[i-1] = nums[i]即可。

这块一个疑问,对于第一个情况,dp[i-1]是大于0的,如果即将加入的nums[i] 小于0,那为啥还要加入,不加他岂不是更大?
这块就要回头看dp的含义了,dp表示以i下标为结尾的,也就是以nums[i]为结尾的最大子数组和,所以当前的nums[i]无论如何必加入。

归根结底是因为这道题要求的是子数组,而不是子序列,子数组要求连续,不能中间扔掉某个值,所以才有了这样的dp定义,以及这样的状态转移公式。

3.初始化dp

如果所给数组只有一个值,那么她的最大子数组肯定是他本身,所以这里dp[0] = nums[0]。

其他值是什么都无所谓了,因为是根据前面和nums推出来的,会覆盖掉。

4.遍历顺序

看dp定义,后一个依赖于前一个,所以从前到后正向遍历没毛病。

这里有一个东西就是返回什么值,要看dp的含义,再来一遍,dp[i] 定义为以下标i为结束下标的子数组的最大和。
如果直接返回dp[-1],那就是以最后一个值为结尾的最大子数组和,显然不对。
所以要找个变量res记录遍历过程中dp[i]的最大值,或者返回的时候直接是max(dp)

记录答案的这个变量res初始化要让他等于所给数组nums的第一个值,预防nums长度等于1的情况。

完整代码

class Solution:
def maxSubArray(self, nums: List[int]) -> int:
# dp[i] 定义为以下标i为结束下标的子数组的最大和

dp = [0] * len(nums)
dp[0] = nums[0]
res = nums[0]
for i in range(1,len(nums)):
dp[i] = max(dp[i-1]+nums[i],nums[i])
res = max(res,dp[i])

print(res)
return res

贪心:

贪心贪的是总和大于0,只要总和小于0,则不要他们了,另起炉灶。

比如 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方!

思路:
遍历nums,从头开始用count累积,如果count一旦加上nums[i]变为负数,那么就应该从nums[i+1]开始从0累积count了,因为已经变为负数的count,只会拖累总和。
在这期间别而忘了记录count的最大值。也就是说,count变为复数之前是记录过总和的了。

举例:

对于示例1: nums = [-2,1,-3,4,-1,2,1,-5,4]

  • count 计数器初始化为0,res = -99999999。
  • 扫描到-2 时, count = -2 ,记录此时count和res的最大值,即res = -2。
  • 判断count是否小于0,若小于0则不要前面的东西了,count另起炉灶,count=0。
  • 扫描到1 时, count = 1 ,记录此时count和res的最大值,即res = 1。
  • 判断count是否小于0,count =1 不小于0。
  • 扫描到-3 时, count = 1-3 = -2 ,记录此时count和res的最大值,即res = 1。
  • 判断count是否小于0,count = -2 ,count另起炉灶,count=0。
  • 扫描到4 时, count = 0+4=4 ,记录此时count和res的最大值,即res = 4。



写不动了,
以此类推。

class Solution:
def maxSubArray(self, nums: List[int]) -> int:

result = -float('inf')
count = 0
for i in range(len(nums)):
count += nums[i]
result = max(result,count)
if count <= 0:
count = 0
return result