链接:53. 最大子数组和 - 力扣(LeetCode)

方法一:自己的直接解法,通过三个辅助数组帮忙。一个是sums用来记录nums数组从0到n-1的和。那么所求子数组的最大和就是右边的一个最大值减去左边的一个最小值。

所以另外两个辅助数组,一个是leftMin数组,用来记录sums数组从0到i的最小值。另一个是rightMax数组,用来记录sums数组从n-1到i的最大值。然后用同样的下标i遍历一下leftMin和rightMax数组,找出rightMax[i]-leftMin[i]的最大值

如果rightMax[i]==leftMin[i],就跳过不处理。因为这样的情况表示sums数组的所有值都一样,也就是说nums数组只有一个值,可能为负数,比计算出来的0还要小。

将前面找到的最大值和nums数组最大值(表示取单个数的最大值)和sums数组最大值(从0开始的子数组)再取最大值得出答案。

 1 class Solution(object):
 2     def maxSubArray(self, nums):
 3         """
 4         :type nums: List[int]
 5         :rtype: int
 6         """
 7         n = len(nums)
 8         sums = [0] * n
 9         sums[0] = nums [0]
10         i = 1
11         while i < n:
12             sums[i] = sums[i-1] + nums[i]
13             i += 1
14         leftMin = [0] * n
15         rightMax = [0] * n
16         leftMin[0] = sums[0]
17         i = 1
18         while i < n:
19             leftMin[i] = min(sums[i], leftMin[i-1])
20             i += 1
21         rightMax[n-1] = sums[n-1]
22         i = n - 2
23         while i >= 0:
24             rightMax[i] = max(sums[i], rightMax[i+1])
25             i -= 1
26         res = max(max(sums), max(nums))
27         i = 0
28         while i < n:
29             if rightMax[i] == leftMin[i]:
30                 i += 1
31                 continue
32             res = max(res,rightMax[i]-leftMin[i])
33             i += 1
34         return res
35         

 方法二:动态规划

关键是想到f[i]表示以i为连续数组最后一位的子数组最大值,这样就可以比较f[i-1] + nums[i] 和nums[i]的最大值,来做出动态转移方程。详见官方题解

 1 class Solution(object):
 2     def maxSubArray(self, nums):
 3         """
 4         :type nums: List[int]
 5         :rtype: int
 6         """
 7         n = len(nums)
 8         pre = nums[0]
 9         res = pre
10         i = 1
11         while i < n:
12             pre = max(nums[i], pre+nums[i])
13             res = max(res,pre)
14             i += 1
15         return res
16