您的位置:首页 > 其它

一种寻找数组中和为最大的子数组的算法

2015-06-16 11:21 405 查看
import java.util.Arrays;

/**
*
*
* 一个寻找数组中和为最大的子数组的算法
* 《算法导论(第3版)》P38
* 算法思想:一个数组的最大子数组在该数组中的位置对于该数组的中点
* 来说有三种情况,1是在中点的左边,2是在右边,3是穿过中点。1,2两
* 种情况可以看成是有问题的一个子问题,利用递归的方法求解。第3种情
* 况可以在一个线性的时间内完成计算
* 算法复杂度:Θ(nlgn)
* */
public class FindMaximumSubarray {

//寻找一个穿过中点的最大子数组
public static int[] findMaxCrossingSubarray(int[] a, int low, int mid, int high){
int[] result = new int[3]; //保存结果,包括子数组的头尾及和值
int leftSum = a[mid];
int sum = 0;
result[0] = mid;
for(int i=mid;i>=low;i--){
sum = sum + a[i];
if(sum > leftSum){
leftSum = sum;
result[0] = i;
}
}
int rightSum = a[mid+1];
sum = 0;
result[1] = mid +1;
for(int i=mid+1;i<=high;i++){
sum = sum + a[i];
if(sum > rightSum){
rightSum = sum;
result[1] = i;
}
}
if(leftSum+rightSum>leftSum)
result[2] = leftSum + rightSum;
else
result[2] = leftSum;
return result;
}

public static int[] findMaximumSubarray(int[] a, int low, int high){
int[] result = new int[3]; //保存结果,包括子数组的头尾及和值
if(low == high){
result[0] = result[1] = low;
result[2] = a[low];
return result;
}else{
int[] leftResult ;
int[] rightResult;
int[] midResult;
//寻找最大子数组的三种情况
leftResult = findMaximumSubarray(a,low,(low+high)/2); //第1种情况
rightResult = findMaximumSubarray(a,(low+high)/2+1,high); //第2种情况
midResult = findMaxCrossingSubarray(a,low,(low+high)/2,high); //第3种情况

//将三种情况的最终结果进行比较
if(leftResult[2] >= rightResult[2] && leftResult[2] >= midResult[2])
return leftResult;
else if(rightResult[2] >= leftResult[2] && rightResult[2] >= midResult[2])
return rightResult;
else
return midResult;
}

}

//测试算法的准确性
//结果为[7,10,43]
public static void main(String[] args){
int[] a={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7};
int[] result = findMaximumSubarray(a,0,a.length-1);
System.out.println(Arrays.toString(result));
System.out.println(Arrays.toString(findMaxCrossingSubarray(a,0,(0+a.length-1)/2,a.length-1)));
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: