题目描述:
输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
思路:没有思路,能想到 联系最大利润的情况,但是还是无法下手!
想清楚了问题:① 每到一个节点,都会有含有该节点的子数组,求和!② 每次得到最大和,和前面的最大和对比,每次留下最大的!
关键难点,就是理解包含 i 的子数组和!还是不好理解,仍然需要想!
根据贡献值正负的思想 来动态规划!
动态规划总结:
① 斐波那契数列和青蛙跳台阶是一个类型:很明确的 当前n处的值和前面 n-1和n-2有联系!有明确的三个值之间的关系,滑动窗口简单!简单的求 n 处的值
② 最大利润:每次到 i 处时,只用将当前值和之前的最小值相减得到新增加的最大利润,和之前的对比,留最大的!
③ 子数组最大和:和最大利润类似,比简单的当前值减去之前最小值难理解!但是有新的思路,就是往前找子数组:要么当前值就是最大;要么就是要包含上一个点在内;此时加上了前面的最大,就得到了当前最大!类推回去是一样的流程
②和③,相比① 多了一个比较的过程,并且每个点处的计算显得更加重要;不是简单的 紧挨的三个点之间的公式!
④ 动态规划要记住:首先动态变化的 要求的结果;其次,动态变化得到的结果不一定是直接需要的答案,如②和③,需要每次对比,记录!
动态规划时间复杂度都是 O(N),空间复杂度可能是 O(1)和O(N)
代码:1)动态规划,时间复杂度 O(N)
class Solution {
public int maxSubArray(int[] nums) {
//这道题的关键:每次计算 包含当前节点的子数组的最大值!!! 不包含当前节点的不算
//每个位置都有,然后比较
//可以声明一个变量,在每次获得的时候都对比记录下最大值!
int dp = nums[0];//每次计算的
int maxSum = nums[0];//记录需要返回的
for(int i = 1;i < nums.length;i++){
//计算
if(dp <= 0) dp = nums[i];
else if(dp > 0) dp = nums[i] + dp;
//记录最大
maxSum = Math.max(dp,maxSum);
}
return maxSum;
}
}