思路:
和最长递增子序列以及最长回文子序列类似,都是动态规划的经典例题
状态转移方程:
dp[i]表示当前数之前的的最大子序和
1)若dp[i-1]为正数,直接加上nums[i]即可,dp[i]=dp[i-1]+nums[i]
2)若dp[i-1]为负数,则dp[i]只取nums[i]一个数,相当于重新选新的子序
最终dp[i]=Math.max(dp[i-1]+nums[i],nums[i])
代码1:
class Solution {
public int maxSubArray(int[] nums) {
int n=nums.length;
int[] dp=new int[n+1];
dp[0]=nums[0];
for(int i=1;i<n;i++){
dp[i]=Math.max(nums[i],dp[i-1]+nums[i]);
}
int res=dp[0];
for(int i=1;i<n;i++){
res=Math.max(res,dp[i]);
}
return res;
}
}
分解:
1)这是第二种dp,当前值依赖于前面所有计算好的值
属于线性规划
2)使用了2次循环,可以合并为一次循环
int res=dp[0];
for(int i=1;i<n;i++){
dp[i]=Math.max(nums[i],nums[i]+dp[i-1]);
res=Math.max(res,dp[i]);
}
3)这里不能直接将最后一个状态返回回去(dp[n-1])。
输出应该是把所有的 dp[0]
、dp[1]
、……、dp[n - 1]
都看一遍,取最大值
同样的情况也适用于「力扣」第 300 题:最长上升子序列。