一、例题一
1)题目描述

2)题目分析:
首先定义dp数组:dp[i] 表示以i位置的数做结尾,并能向左延申的最大累加和。并且每一个i位置的dp值都表示从0~i的最优情况,即每一次更新dp[i]时只需和dp[i - 1]进行比较,如果dp[i - 1]<= 0说明再往左也“无利可图”,所以我们更新
dp[i] = Math.max(nums[i] , dp[I - 1] + nums[i])。
扩展:求最长区间的left、right
我们需要一个l、r和pre来记录每一次更新的答案,然后left、right、sum为最终答案。
当 pre >= 0 pre += nums[r];
pre < 0 pre = nums[r] ; l = r;
样例 【5 , -2 , 3 , -9 , 4 , -1 ,3 , 1 , -9 , 4】
3)代码
package class70;
public class 最大子数组和 {
public int maxSubArray1(int[] nums) {
int n = nums.length;
//dp[i] : 子数组必须以i位置的数做结尾,往左延申出来的最大累计和
int dp[] = new int[n];
dp[0] = nums[0]; //第一个就是nums[0]本身
int ans = dp[0]; //第一个答案需要更新为数组的第一个
for(int i = 1 ; i < n ; i ++) {
dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]); //两种情况,因为dp[i - 1]表示i - 1位置前的最大累加和,但是有可能dp[i - 1]会是一个负数,所以需要取两种情况的最大值
ans = Math.max(ans, dp[i]); //更新ans
}
return ans;
}
//空间压缩
public int maxSubArray2(int[] nums) {
int n = nums.length;
int ans = nums[0];
int pre = nums[0]; //代替dp的更新
for(int i = 1 ; i < n ; i ++) {
pre = Math.max(nums[i], pre + nums[i]);
ans = Math.max(ans , pre);
}
return ans;
}
//要求返回left、right、sum
public static int left;
public static int right;
public static int sum;
public static void extra(int nums[]) {
sum = Integer.MIN_VALUE;
int pre = Integer.MIN_VALUE;
for(int l = 0 , r = 0 ; r < nums.length ; r ++) {
if(pre >= 0) {
pre += nums[r];
}else {
pre = nums[r];
l = r;
}
if(pre > sum) {
left = l;
right = r;


776

被折叠的 条评论
为什么被折叠?



