问题描述:一个数值型数组,其子数组有多个,求其子数组中最大的和值。所谓和值,是指数组所有元素相加的和。
解法(1):扫描法,维护max变量,存储最大和,其初始值为data[0]。假设最大和子数组的第一位下标为i,i从0到n-1,对于每个i值,从data[i]开始,进行累加,每加一个数,与max变量比较一次,如果比max大,就用其代替max。算法实现:
public int maxSum(int[] data){
int max = data[0];
for(int i=0; i<data.length; i++){
int tmpSum = 0;
for(int j=i; j<data.length; j++){
tmpSum+=data[j];
if(tmpSum>max) max = tmpSum;
}
}
return max;
}
解法(2):动态规划法,假设f[i]表示以第i位为结尾的的连续子数组的最大和,那么,当f[i-1]为负时,f[i] = data[i];当f[i-1]为正时,则f[i] = f[i-1]+data[i];算法实现:
public class Main{
public static void main(String[] args){
int[] data = {-1,4,-1,4,6,3,-5,9,-8,7,-6};
Result res = new Main().maxSum(data);
System.out.println(res.begin+" "+res.end+" "+res.sum);
}
class Result{//定义一个类来存储最大和连续子序列的初始下标,结尾下标以及和
int begin;
int end;
int sum;
}
public Result maxSum(int[] data){
Result res = new Result();
int[] aa = new int[data.length];
aa[0] = data[0];
int max = aa[0];//存储最大的和值
int begin = 0;//表征当前子数组的初始下标
int end = 0;//表征当前子数组的结尾下标
for(int i=1; i<data.length; i++){
if(aa[i-1]>0) {
aa[i] = aa[i-1]+data[i];//当以aa[i-1]结尾的连续子数组和为正值,则aa[i]为aa[i-1]+data[i]
end = i;
}
else {
aa[i] = data[i];//当以aa[i-1]结尾的连续子数组和为负值,则aa[i]为data[i]
begin = i;
end = i;
}
if(aa[i]>max) {//如果当前的aa[i]大于max,则储存此时对应的连续子数组的和值,起始下标和结尾下标
max = aa[i];
res.sum = max;
res.begin = begin;
res.end = end;
}
}
return res;
}
}