A[low..high]的任何子数组A[i,j]所处的位置必定是一下三种情况之一:
- 完全位于子数组A[low..mid]中,low< =i<=j<=mid
- 完全位于子数组A[mid+1..high]中,mid < i< =j< =high
- 跨越了中点,low< =i< =mid < j< =high
思路:
- 递归地求解A[low..mid]和A[mid+1..high]的最大子数组
- 寻找跨越中点的最大子数组
- 选取这三中情况中的最大值
1.寻找跨越中点的最大子数组
/***
*
* @param A 数组
* @param low 下界
* @param mid 中点
* @param high 上界
* @return 最大子数组(跨越mid)的下标范围和最大子数组的和
*/
public static int[] findMaxCrossingSubArray
(
int[] A,
int low,
int mid,
int high
)
{
//找出左半部的最大子数组,必须包括A[mid]
int left_sum=0; //目前找到的最大和
int sum=0; //A[i..mid]的和
int max_left=mid; //目前找到的最大和的下标
for (int i = mid; i >=low; i--) {
sum=sum+A[i];
if (sum>left_sum) {
left_sum=sum;
max_left=i;
}
}
//找出右半部的最大子数组,必须包括A[mid]
int right_sum=0; //目前找到的最大和
sum=0; //A[mid+1..i]的和
int max_right=mid; //目前找到的最大和的下标
for (int j = mid+1; j <= high; j++) {
sum=sum+A[j];
if (sum>right_sum) {
right_sum=sum;
max_right=j;
}
}
//返回结果
return new int[]{max_left,max_right,left_sum+right_sum};
}
2.递归地求解A[low..mid]和A[mid+1..high]的最大子数组,选取这三中情况中的最大值
public static int[] findMaximumSubArray(int[] A,int low,int high)
{
//只有一个元素
if (high==low) {
return new int[]{low,high,A[low]};
}
else {
int mid=(low+high)/2;
int[] left_result =findMaximumSubArray(A,low,mid);
int[] right_result=findMaximumSubArray(A,mid+1,high);
int[] mid_result =findMaxCrossingSubArray(A,low,mid,high);
if(left_result[2]>=right_result[2]
&&left_result[2]>=mid_result[2])
{
return left_result;
}else if (right_result[2]>=left_result[2]
&&right_result[2]>=mid_result[2])
{
return right_result;
}else {
return mid_result;
}
}
}