E-53. Maximum Subarray
如果这题没有头绪, 或者看不懂我下面的东西的话, 可以看看这个哥们的视频, 另外他频道里的东西都很有意思, 刚开始刷题的话, 无聊的时候可以去看几个视频. 是现在在马里兰帕克读书的很聪明的一个小兄弟.
7:49 开始讲DP的解法, 前面在讲暴力解, 不感兴趣可以略过
# 1 dp
'''
先尝试把问题转换成一个可解的版本:
给一串数nums = [1,2,3,4,...], 找到一个subarray, 使得subarray中数字的sum是所有subarray
中最大的那个subarray, 返回sum即可(不需要保存subarray, 保存也差别不大应该..).
因为subarray有起始点和终止点, 我们可以用array[s,e](inclusive)来表示某个唯一的subarray.
s和e分别是数字在nums里的下标. 因此我们要求, 使得array[s,e]中数字的sum最大的那个array[s,e]的sum
=> 而这个maxsubarray[s,e]实际上是由s和e来定义的. 所以问题变成了找到那个s和e.
=> 但是一顿绞尽脑汁都不知道如何快速地找s和e(非暴力), 看来我们需要站在更高的角度看问题, 我们是不是不需
要找到那个s和e?而可以直接得出那个sum? how?
=============================================================
说实话我也不知道如果我没看答案该怎么思考这个题目, 但是如果我们看了答案, 再回来反思, 可以进行如下思考:
既然我们要找有最大sum的那个subarray, 而且每一个subarray都有一个右边界, 如果我们能找到这个
nums中所有的, 以某一个index为右边界的所有subarray中sum最大的那个subarray的sum, 我们记作sum_i
, 然后从中选最大的那个sum, 即是我们要找的结果.
所以我们有了以下思路:
设f[i]是 -> *如果nums[i]一定在该maxSubArray里的情况下*, 下标0到i的maxSubArray的值(所谓下标0到
i的maxSubArray的意思是, 假设我们已经遍历过一次nums中下标为0到i的数, 我们得到了一个maxSubArray
, 这个maxSubArray的sum()是f[i])
---f[i] = max(nums[i] + f[i-1], nums[i]) i > 0
我们不难发现--
---f[0] = nums[0] i == 0
(或者对于i>0, 可以写作另一种形式f[i] = nums[i] + f[i-1]
if f[i-1] > 0
else nums[i])
因此对于nums=[-2,1,-3,4,-1,2,1,-5,4]
从左往右遍历nums:
1. 遍历到nums[0]的时候, 显然f[0] = maxSubArray = nums[0] = -2
2. 遍历到nums[1]的时候, f[1] = maxSubArray如何计算呢?
对于此时的f[1]来说, 有以下2种选择, 根据开头的定义, f[1]就意味着第1号位置的数一定在maxSubArray
中, 所以我们要看f[0]到底要不要接着参与到f[1]中, 即:
1. 不舍弃f[0], 并且加上当前的nums[1]组成新的f[1] = f[0] + nums[1] = -1
2. 舍弃f[0], 从当前的nums[1]重新开始纳入maxSubArray, f[1] = nums[1] = 1
(再次强调, 根据定义, 因为f[1]一定会取nums[1], 所以并不存在nums[1]被舍弃的情况.)
而, 是否舍弃f[0], 显然要看f[0]对f[1]的影响是正面的还是负面的.
对于这道题显然要选择让f[1]最大化的情况.
而在这道题目里, 让f[1]最大化的情况就是f[0]>0.
即我们选择 which is the max(f[0] + nums[1], nums[1])
(
所以下面的code循环里的那一行能改成这样:
max_sum_lst.append(max([nums[i] + max_sum_lst[i-1],nums[i]]))
)
3. ...递推即可
所以我们能得到上面的公式
最终我们从f[0]到f[n]中选出最大的那个f[i]即可.
'''
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
if not nums:
return None
if len(nums)==1:
return nums[0]
max_sum_lst=[nums[0]]
for i in range(1,len(nums)):
max_sum_lst.append(nums[i] + max_sum_lst[i-1] if max_sum_lst[i-1] > 0 else nums[i])
return(max(max_sum_lst))
Last updated
Was this helpful?