问题描述
输入是具有n个浮点数的向量x(数组),输出是输入向量的任何连续子向量的最大和,例如输入为[31,-41,59,26,-53,58,97,-93,-23,84],那么输出为x[2..6]的总和,即187.
求解方法
简单直白法
直接求出所有满足0<=i<=j<=n的(i,j)整数对进行迭代,计算x[i…j]的总和,并检验该总和是否大于迄今为止的最大总和,时间复杂度O(n^3),称为立方算法,效率较低。
public static int f1(int[] a){ int len=a.length; int maxsofar=0; for(int i=0;i<len;i++){ for(int j=i;j<len;j++){ int sum=0; for(int k=i;k<=j;k++) sum+=a[k]; maxsofar=max(sum,maxsofar); } } return maxsofar; } public static int max(int x,int y){ return x>y?x:y; } public static void main(String[] args) { int[] a={31,-41,59,26,-53,58,97,-93,-23,84}; int re=f1(a); System.out.println(re); }
平方算法
x[i..j]的总和与前面已计算出的总和x[x…j-1]的总和相关,此方法时间复杂度为O(n^2)。
public static int f2(int []a){ int len=a.length; int maxsofar=0; for(int i=0;i<len;i++){ int sum=0; for(int j=i;j<len;j++){ sum+=a[j]; maxsofar=max(maxsofar,sum); } } return maxsofar; }
扫描算法
从数组的最左端开始扫描,一直到最后端,并记下所遇到的最大总和子向量。前i个元素中,最大总和子数组要么在前i-1个元素中(存储在maxsofar中),要么其结束为止为i(存储在maxendinghere中)。时间复杂度为O(n),效率较高。
public static int f3(int []a){
int len=a.length;
int maxsofar=0,maxendinghere=0;
for(int i=0;i<len;i++){
maxendinghere=max(maxendinghere+a[i],0);
maxsofar=max(maxendinghere,maxsofar);
}
return maxsofar;
}