4.1 最大子陣列問題(分治法)-NlogN
阿新 • • 發佈:2019-02-12
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;
}
}
}