题目描述
求连续子数组的最大和,例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和。
题解:
方法一:
观察法
例如 {1,-2,3,10,-4,7,2,-5},最大的子数组为 {3,10,-4,7,2},输出18。
我们试着从头到尾逐个累加每个数字,初始化和为0。第一步加上第一个数字1,此时和为1。接下来第二步加上数字-2,和就变成了-1。第三步加上数字3。我们注意到由于此前累加的和是-1,小于0,那如果用-1加上3,得到的和是2,比3本身还小。也就是说从第一个数字开始的子数组的和会小于从第三个数字开始的子数组的和。因此我们不用考虑从第一个数字开始的子数组,之前累加的和也就被抛弃。应该从第三个数字重新开始累加,此时得到和为3。第四步加10,得到13。第五步加-4,得到9。我们发现由于-4是一个负数,因此累加-4之后得到的和比原来的和还要小。因此我们要把之前得到的和13保存下来,他有可能是最大的子数组的和。第六步加上数字7,的16,比之前保存的13好大,把max由13更新为16。第七步加上2,累加得到的和为18,同时我们也要更新最大子数组的和。第八步加上最后一个数字-5,得到13小于max,因此最终最大的子数组的和为18。
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int max = Integer.MIN_VALUE;
int sum = 0;
for (int i = 0; i < array.length; i++) {
if (sum <= 0) {//如果以前的累加为负数,那么从头开机记,因为加上负数一定变小
sum = array[i];
}else{
sum += array[i];
}
if (sum > max) {
max = sum;
}
}
return max;
}
}
方法二:动态规划
和方法一其实是一个道理
f[i] 表示以第i个数字结尾的子数组的最大和,那么需要求 max(f[i])
递推公式:
以第 i-1 个数字结尾的子数组中最大和小于0时,如果把这个负数与第 i 个数累加,得到的结果比第 i 个数字本身还要小,所以这种情况,f[i]=array[i] ; 否则 f[i]=f[i-1]+array[i];
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
if (array == null || array.length == 0) {
return 0;
}
int[] f=new int[array.length];
f[0]=array[0];
int max = Integer.MIN_VALUE;
for (int i = 1; i < array.length; i++) {
if(f[i-1]>0){
f[i]=f[i-1]+array[i];
}else{
f[i]=array[i];
}
if(f[i]>max){
max=f[i];
}
}
return max;
}
}