LeetCode-53. Maximum Subarray( 最大子序和)(一维dp)
- 递归写法
- 一维dp数组
- 滚动优化
递归写法
递归和动态规划永远是可以转换的,我们可以从数组的最后开始往前看,对于当前数nums[i],以这个nums[i]结尾的最大值一定是你前面的所有数求出一个最大的子序和(但是由于是子数组,所以必须是判断前一个数)+我自己(nums[i]),所以这是一个递归的过程,边界条件就是i = 0时,最大子序和就是自己。
public int max;
public int maxSubArray(int[] nums){
max = nums[0];
process(nums,nums.length-1);
return max;
}
public int process(int[] nums,int index){
if(index == 0){
return nums[0];
}else {
int pre = process(nums,index-1); //先给我求出前面的最大子序和
int cur = pre > 0 ? pre + nums[index] : nums[index];
max = Math.max(cur,max);
return cur;
}
}
一维dp数组
动态规划就是从小问题到大问题,递归相反的方向,我们可以正向的保存一个以每一个数结尾的最大子序和的数组,然后递推到最后一个,其中使用个max保存最大值;
public int maxSubArray(int[] nums) {
int[] ends = new int[nums.length];
ends[0] = nums[0];
int max = ends[0];
for(int i = 1; i < nums.length; i++){
ends[i] = ends[i-1] > 0 ? ends[i-1] + nums[i] : nums[i];
max = Math.max(max,ends[i]);
}
return max;
}
滚动优化
类似二维dp的滚动数组优化,因为每个位置只需要它前面的一个位置,所以我们只需要用一个变量保存即可。
public int maxSubArray(int[] nums) {
int preMax = nums[0];
int max = nums[0];
for(int i = 1; i < nums.length; i++){
preMax = preMax > 0 ? preMax + nums[i]: nums[i];
max = Math.max(max,preMax);
}
return max;
}