Descrpiton:
给定一个数组,比如说
int[] a = {1, 4, -5, 9, 8, 3, -6};
int[] b = {1, -2, 3, 10, -4, 7, 2, -5};
求出其最大子数组和(最大子数组必须是连续的)
其最大子数组为 9, 8, 3 ,所以和为 20
b 的和是 18
Solution:
本题可以用动态规划来做,俗称 dp
dp最重要的就是状态转移方程(这一步和前一步的关系):
dp[i] = max(dp[i - 1] + array[i], array[i])
这里dp代表的是前 i 个元素最大子数组和(必须使用到第i - 1个元素,如果 dp[i-1] + array[i] > array[i])
理由是:因为子数组是要连续的,所以如果要用之前的值,必须使用到第i - 1个元素。所以对于任意dp[i],它必须使用到第 i 个元素为了下一步使用。比如 i = 2,则 dp = 1 + 4 + -5 = 0. 这也就是为什么这里要用max来记录临时最大值,而不是直接返回 dp[array.length + 1]
综合代码如下:
private int largesub(int[] a) {
//dp 第一步分配一个数组空间
int[] dp = new int[a.length + 1];
//dp 第二步初始化初始位置的值
dp[0] = 0;
int max = 0;
//dp 第三步写出状态转移方程 dp[i] = max( dp[i - 1] + arr[i], arr[i] )
//这里dp代表的是前 i 个元素最大子数组和(必须使用到第i - 1个元素,如果 dp[i-1] + array[i] > array[i])
//理由是:因为子数组是要连续的,所以如果要用之前的值,必须使用到第i - 1个元素。
//如果之前元素之和小于0,则使用第 i 个元素。使用max记录最大值(通常dp返回dp最后一个元素即可,这里不太一样)
for(int i = 0; i < a.length; ++i) {
dp[i + 1] = Math.max(dp[i] + a[i], a[i]);
max = dp[i + 1] > max ? dp[i + 1] : max;
}
return max;
}