从一串数据中算出最大的子序列和,这里提供了三种方法,方案一到方案三中算法由劣到优。
例如:-2,11,-4,13,-5,-2,答案为20(从A2到A4)
方案一:
public static int maxSubSum(int a []){
int maxSum=0;
for(int i=0; i<a.length; i++)
for(int j=i; j<a.length; j++){
int thisSum=0;
for(int k=i; k<=j; k++)
thisSum+=a[k];
if(thisSum>maxSum)
maxSum=thisSum;
}
return maxSum;
}
此种方案的时间复杂度大概为N的三次方,可以这样来分析:三次for循环,每次循环为N,所以三次迭代的循环大概为N的三次方。
方案二:
public static int maxSubSum(int a []){
int maxSum=0;
for(int i=0; i<a.length; i++){
int thisSum=0;
for(int j=i; j<a.length; j++){
thisSum+=a[j];
if(thisSum>maxSum)
maxSum=thisSum;
}
}
return maxSum;
}
此种方案的时间复杂度为N的平方,理解与第一种相同,这种方法相对于第一种方案较好。
方案三:
public static int maxSubSum(int a []){
int maxSum=0;
int thisSum=0;
for(int i=0; i<a.length; i++){
thisSum+=a[i];
if(thisSum>maxSum)
maxSum=thisSum;
else if(thisSum<0)
thisSum=0;
}
return maxSum;
}
此种方案的时间复杂度为N,在三种方案中最优。运行时间是明显的,但是不容易看出正确性。我们可以分析出这样的结论,如果a[i]是负的,那么它不可能代表最优序列的起点,因为任何包含a[i]的作为起点的子序列都可以通过用a[i+1]作为起点而改进。类似地,任何负的子序列不可能是最优子序列的前缀(原理相同)。
小结:其实除此三种算法,还有一种时间复杂度为N*logN的递归算法。方法稍微有点复杂,如果读者感兴趣可以借鉴其他文章。
例如:-2,11,-4,13,-5,-2,答案为20(从A2到A4)
方案一:
public static int maxSubSum(int a []){
int maxSum=0;
for(int i=0; i<a.length; i++)
for(int j=i; j<a.length; j++){
int thisSum=0;
for(int k=i; k<=j; k++)
thisSum+=a[k];
if(thisSum>maxSum)
maxSum=thisSum;
}
return maxSum;
}
此种方案的时间复杂度大概为N的三次方,可以这样来分析:三次for循环,每次循环为N,所以三次迭代的循环大概为N的三次方。
方案二:
public static int maxSubSum(int a []){
int maxSum=0;
for(int i=0; i<a.length; i++){
int thisSum=0;
for(int j=i; j<a.length; j++){
thisSum+=a[j];
if(thisSum>maxSum)
maxSum=thisSum;
}
}
return maxSum;
}
此种方案的时间复杂度为N的平方,理解与第一种相同,这种方法相对于第一种方案较好。
方案三:
public static int maxSubSum(int a []){
int maxSum=0;
int thisSum=0;
for(int i=0; i<a.length; i++){
thisSum+=a[i];
if(thisSum>maxSum)
maxSum=thisSum;
else if(thisSum<0)
thisSum=0;
}
return maxSum;
}
此种方案的时间复杂度为N,在三种方案中最优。运行时间是明显的,但是不容易看出正确性。我们可以分析出这样的结论,如果a[i]是负的,那么它不可能代表最优序列的起点,因为任何包含a[i]的作为起点的子序列都可以通过用a[i+1]作为起点而改进。类似地,任何负的子序列不可能是最优子序列的前缀(原理相同)。
小结:其实除此三种算法,还有一种时间复杂度为N*logN的递归算法。方法稍微有点复杂,如果读者感兴趣可以借鉴其他文章。