携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情 >>
一、题目描述
给定一个长度为 n 的数组,数组中的数为整数。 请选择一个非空连续子数组,使得该子数组所有数之和尽可能大,求这个最大值。
二、示例
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6。
三、思路分析
1.本题可以使用简单动态规划来解决
2.在使用动态规划时,假设 curr 表示数组的当前位置,我们可以考虑不加 curr 之前子数组的最大和,以及加上 curr 时子数组的最大和。使用 S(curr) 表示以 curr 结尾的子数组的和Sum[curr]
,则 S(curr-1) 表示以 curr-1 结尾的数组的和Sum[curr-1]。
3.考虑 nums[curr] 单独成为一段,还是加入 S(curr-1)。既
S(curr) = max{S(curr-1)+nums[curr],nums[curr]}。
用一个 S 数组来保存 S(curr) 的值,用一个循环求出所有 S(curr)。考虑到 S(curr) 只和 S(curr-1) 相关,于是我们可以只用一个变量 pre 来维护对于当前 S(curr) 的 S(curr-1) 的值是多少。
四、代码
public int maxSubArray(int[] nums) {
int pre = 0, maxAns = nums[0];
for (int x : nums){
pre = Math.max(pre+x, x);
maxAns = Math.max(maxAns, pre);
}
return maxAns;
}
五、总结
本题使用动态规划思想,学习了简单动态规划思想的使用,在使用动态规划时要仔细思考,如何合理的定义子问题,例如这道题,将子问题定义为S(curr) = max{S(curr-1)+nums[curr],nums[curr]},并由一个个子问题的结果最后得出最终问题的答案,将时间复杂度降为O(n)使得程序仅使用一个循环即可得出结果,并将空间复杂度降为O(1)。本题还可以使用分治的思想解决,具体解法待补充。。。