总结|题解四十二

53. 最大子序和 【总结|题解四十二】给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
(来源:力扣(LeetCode))
思路:这道题使用动态规划的思路解决并不难。
我们需要求的是一个连续数组,所以当我们分解子问题的时候,不能求的是前k个元素的最大子数组之和,因为这样很可能会跟新元素不连续,就不出最大和。
如示例所示,输入: [-2,1,-3,4,-1,2,1,-5,4],
f(1) 即[-2]的最大子数组和为 -2
f(2) 即[-2,1]的最大子数组和为 1
f(3) 即[-2,1,-3]的最大子数组和为 1
f(4) 即[-2,1,-3,4]的最大子数组和为 4
f(5) 即[-2,1,-3,4,-1]的最大子数组和为 [ 4,-1] = 2
我们可以看到,f(3)的最大子数组和为1,位于数组的中部,当f(4)加入新元素时,我们想知道f(3)的最大数组和能否和新元素求出最优解时,却发现它们并不连续。
因此,我们分析子问题的时候只需要考虑数组尾部的子数组,这样加入新元素时就是连续的。重新计算f(3)、f(4)的最大和:
f(3) 即[-2,1,-3]的最大子数组和为 [1, -3] = -2
f(4) 即[-2,1,-3,4]的最大子数组和为 4
我们可以写出递推关系,计算[0…k]的子数组最大和时,要么是把新元素nums[k - 1]加入到前一个子问题的最大和中,要么新元素nums[k -1]就是最大和。
递推公式为 f(k) = max{f(k -1) + nums[k -1], nums[k -1]},
简化可得,f(k) = max{f(k -1), 0} + nums[k - 1].

class Solution { public int maxSubArray(int[] nums) { int n = nums.length; int[] dp = new int[n + 1]; dp[0] = 0; int res = Integer.MIN_VALUE; for (int i = 1; i <= n; i++) { dp[i] = Math.max(dp[i - 1], 0) + nums[i - 1]; res = Math.max(res, dp[i]); }return res; } }

    推荐阅读