目录
解法1 暴力法(比较所有子列和,取最大值)O(n^3)
// 暴力求解,求出每个子列和,复杂度 三次方
public static int MaxSum(int arr[]){
// 求最大子列和, 先取子列并求和
int maxSum = 0;
for(int i = 0; i < arr.length; i++){ // i 为子列左侧位置
for(int j = i; j < arr.length; j++ ){ // j为子列右侧位置
int thisSum = 0;
for(int k = i; k <= j;k++){ // k进行子列和计算
thisSum += arr[k];
if (maxSum < thisSum){
maxSum = thisSum;
}
}
}
}
return maxSum;
}
解法2:O(n^2) 不再做重复的加法
// 解法2
public static int MaxSum2(int arr[]){
int maxSum = 0;
for(int i = 0; i < arr.length; i++){ // i为子列左侧位置
int thisSum = 0; // arr[i] 到 arr[j]的子列和
for(int j = i ; j < arr.length; j++){
thisSum += arr[j];
if(thisSum > maxSum){
maxSum = thisSum;
}
}
}
return maxSum;
}
}
解法3: 分而治之
利用递归求解,设置递归结束条件后,分别求出左侧子列和右侧子列的最大子列和,再求跨越边界的最大子列和,返回三个数中的最大值
// 分而治之,递归解决左右两侧的最大连续子列和
//返回最大子列和
public static int MaxSum3(int arr[]){
int maxSum;
maxSum = DivideandCounter(arr,0,arr.length -1);
return maxSum;
}
// 返回三个数中的最大值
public static int Max3(int a, int b, int c){
int max = 0;
if(a > max){
max = a;
}
if (b > max){
max = b;
}
if(c > max){
max = c;
}
return max;
}
public static int DivideandCounter(int arr[], int left, int right){
int maxLeftSum, maxRightSum; //存放左右两个子列的结果
// 递归终止条件,子列只有一个数字,正数返回数值,负数返回0
if(left == right){
if(arr[left] > 0){
return arr[left];
}else{
return 0;
}
}
// 先将数组分成两个部分
int center = (left + right) / 2; // 找到中分点
// 递归调用解决左侧子列和右侧子列问题
maxLeftSum = DivideandCounter(arr, left, center);
maxRightSum = DivideandCounter(arr, center + 1 , right);
// 解决跨越边界的问题
int rightBorderSum, maxRightBorderSum;
// 从中心向右方扫描
maxRightBorderSum = 0;
rightBorderSum = 0;
for(int i = center + 1 ; i <= right; i++){
rightBorderSum += arr[i] ;
if(maxRightBorderSum < rightBorderSum){
maxRightBorderSum = rightBorderSum;
}
}
// 从中心往左侧扫描
int leftBorderSum, maxLeftBorderSum;
maxLeftBorderSum = 0;
leftBorderSum = 0;
for(int i = center ; i >= left; i --){
leftBorderSum += arr[i] ;
if(maxLeftBorderSum < leftBorderSum){
maxLeftBorderSum = leftBorderSum;
}
}
return Max3(maxLeftSum, maxRightSum, (maxLeftBorderSum + maxRightBorderSum)) ;
}
解法4 在线处理
“在线”的意思是指每输入一个数据就进行即时处理,在任何一个地方中止输入,算法都能正确给出当前的解。
算法效率高是有代价的:其正确性不明显(他人难以理解算法是如何工作的)
public static int MaxSum4(int arr[]){
int thisSum = 0;
int maxSum = 0;
for(int i = 0; i < arr.length ; i++){
thisSum += arr[i]; // 每输入一个数都进行一次处理
if(thisSum > maxSum){
maxSum = thisSum;
}else if(thisSum < 0){ // 如果当前子列为负,则不可能使后面子列和增大,归零
thisSum = 0;
}
}
return maxSum;
}