- 算法描述
求解数组中最大子数组的位置,和归并排序类似,也是使用分治法,最大字数组的位置要么出现在原数组的左半部分,要么出现在原数组的右半部分,要么一部分在左半部分,一部分在右半部分。 - 算法实现
package sxd.learn.algorithms;
public class Find_Max_SubArray {
public static void main(String[] args){
int[] iArray = {13, -3, -25, 20, -3,
-16, -23, 18, 20, -7,
12, -5, -22, 15, -4,
7};
IndexAndSum result = findMaxSubarray(iArray, 0, iArray.length -1);
System.out.println("iArray[" + result.lowIndex + ".."+ result.highIndex + "]"
+ "\t" + "sum:" + result.sum);
}
/**
* @param iArray
* @return 最大子数组下标及其和的对象
*/
public static IndexAndSum findMaxSubarray(int[] iArray, int low, int high){
if (low == high) {
return new IndexAndSum(low, high, iArray[low]);
}else{
int mid = (low + high) / 2;
IndexAndSum leftObject = findMaxSubarray(iArray, low, mid);
IndexAndSum rightObject = findMaxSubarray(iArray, mid + 1, high);
IndexAndSum crossObject = findMaxCrossingSubarray(iArray, low, mid, high);
if (leftObject.sum > rightObject.sum && leftObject.sum > crossObject.sum) {
return leftObject;
}else if(rightObject.sum > leftObject.sum && rightObject.sum > crossObject.sum){
return rightObject;
}else{
return crossObject;
}
}
}
/**
* @param iArray
* @return 下标元组划定跨越中点的最大字数组的边界和最大字数组中值的和对象
*/
public static IndexAndSum findMaxCrossingSubarray(int[] iArray, int low, int mid, int high){
int left_sum = Integer.MIN_VALUE;
int right_sum = Integer.MIN_VALUE;
int max_left = 0;
int max_right = 0;
int sum = 0;
for(int i = mid; i >= low; i--){
sum += iArray[i];
if(sum > left_sum){
left_sum = sum;
max_left = i;
}
}
sum = 0;
for(int j = mid + 1; j<= high; j++){
sum += iArray[j];
if(sum > right_sum){
right_sum = sum;
max_right = j;
}
}
return new IndexAndSum(max_left, max_right, left_sum + right_sum);
}
private static class IndexAndSum{
public int lowIndex;
public int highIndex;
public int sum;
public IndexAndSum(int lowIndex, int highIndex, int sum) {
this.lowIndex = lowIndex;
this.highIndex = highIndex;
this.sum = sum;
}
}
}
- 算法分析
最大子数组问题不是一个典型的分治问题,是由于findMaxCrossingSubarray这个过程。