起因:给定一个整数序列,可能包含正数或负数。设计一个算法寻找它的一个子序列,其数字的和最大。
方案一(最耗时) 、
/**
* 全部结果都进行比较
* eg: 序列集合是 {1,2,3}
* i j thisSum maxSum
* 0 0 1 1
* 1 3 3
* 2 6 6
* 1 1 2 6
* 2 5 6
* 2 2 3 6
*
* 最终把maxSum 返回就是最大子序列和
* */
public static int maxSubSum1(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;
}
方案二、(折半递归 耗时较方案一更少)
/**
* 结果折半进行比较 递归 效率比第一种快速很多
* eg: 序列集合是 {1,2,3}
*
* 递归 1 2 3
* left 0 0 2
* right 2 1 2
* leftMaxSum maxSubSumRec(a, 0,1)=>3 maxSubSumRec(a,0,0)=>1 -
* rightMaxSum maxSubSumRec(a,2,2)=>3 maxSubSumRec(a,1,1)=>2 -
* maxLeftBorderSum 3 1 -
* maxRightMaxSum 3 2 -
* maxSum 6 3 3
* 最终把maxSum 返回就是最大子序列和
* */
public static int maxSubSumRec(int[] a, int left, int right) {
if (left == right) {
return a[left];
}
int center = (left + right) / 2;
int leftMaxSum = maxSubSumRec(a, left, center);
int rightMaxSum = maxSubSumRec(a, center + 1, right);
int leftBorderSum = 0, maxLeftBorderSum = 0;
for (int i = center; i >= left; i--) {
leftBorderSum += a[i];
if (leftBorderSum > maxLeftBorderSum) {
maxLeftBorderSum = leftBorderSum;
}
}
int rightBorderSum = 0, maxRightBorderSum = 0;
for (int i = center + 1; i <= right; i++) {
rightBorderSum += a[i];
if (rightBorderSum > maxRightBorderSum) {
maxRightBorderSum = rightBorderSum;
}
}
return max2(leftMaxSum, rightMaxSum, maxLeftBorderSum + maxRightBorderSum);
}
// 获取最大值
public static int max2(int a, int b, int c) {
int max = a;
if (max < b) {
max = b;
}
if (max < c) {
max = c;
}
return max;
}
public static int maxSubSum2(int[] a) {
return maxSubSumRec(a, 0, a.length - 1);
}
方案三、(最佳方案 耗时较以上两个方案更少)
/**
* eg: {1,-2,4,6,-7,9}
* i thisSum maxSum
* 0 1 1
* 1 0 1
* 2 4 4
* 3 10 10
* 4 3 10
* 5 12 12
* */
public static int maxSubSum3(int[] a) {
int maxSum =0 ,thisSum =0;
for(int i=0;ilength;i++){
thisSum+=a[i];
if(thisSum>maxSum){
maxSum=thisSum;
}else if(thisSum<0){
thisSum=0;
}
}
return maxSum;
}