分治法的运用条件:
1.原问题可以分解为若干与原问题的解;
2.子问题可以分解并可以求解;
3.子问题的解可以合并为原问题的解;
4.分解后的子问题应互相独立,即不包含重叠子问题
子序列的最大和只可能出现在三个位置:1、序列的左半部分;2、序列的右半部分;3、序列中横跨左右部分(一定包含中间元素)
1、左半部分:递归调用该函数(左半部分子串),maxLeftSum递归到left==right;
2、右半部分:递归调用该函数(右半部分子串)maxRightSum,递归到left==right;
3、中间部分:从中间元素算起,其往左走的最大和maxLeftBorderSum+其往右走的最大和maxRightBorderSum,则中间结果的最大和为maxLeftBorderSum+ maxRightBorderSum;
比较maxLeftSum,maxRightSum,maxRightBorderSum+ maxRightBorderSum中的最大值;
代码位置:
import java.util.Arrays;
public class maxArray {
public static void main(String[] args) {
//将数组从中间分开得到两个子序列 最大值将会在左序列最大值、右序列最大值、跨中线序列最大值中产生
int arr[] = new int[] {-1, 2, -5, 7, 8, -5 };
System.out.println("最大子序列和为:"+maxArray.maxsum(arr));
}
public static int maxSubSum(int arr[], int left, int right) {
if (left == right) {
return arr[left];
}
int mid = (left + right) >>> 1; // 求中间位置
//递归找出左序列最大连续子序列和maxLeftSum
int maxLeftSum = maxSubSum(arr, left, mid);
//递归找出右序列最大连续子序列和maxRightSum
int maxRightSum = maxSubSum(arr, mid + 1, right);// 求右序列最大连续子序列
int maxLeftBorderSum = 0, maxRightBorderSum = 0;// 跨边境左序列最大连续子序列,跨边境右序列最大连续子序列
int leftBorderSum = 0, rightBorderSum = 0;
//跨中线最大连续子序列是由跨边境左序列最大连续子序列maxLeftBorderSum和跨边境右序列最大连续子序列maxRightBorderSum中产生
for (int i = mid; i >= left; i--) {// 求跨边境左序列最大连续子序列maxLeftBorderSum
leftBorderSum += arr[i];
if (leftBorderSum > maxLeftBorderSum) {
maxLeftBorderSum = leftBorderSum;
}
}
for (int j = mid + 1; j <= right; j++) {// 求跨边境右序列最大连续子序列maxRightBorderSum
leftBorderSum += arr[j];
if (rightBorderSum > maxRightBorderSum) {
maxRightBorderSum = rightBorderSum;
}
}
//递归找出右序列最大连续子序列和maxMidSum
int maxMidSum = maxLeftBorderSum + maxRightBorderSum;
return max(maxLeftSum, maxRightSum, maxMidSum);
}
//找最大值
public static int max(int a, int b, int c) {
int temp = Math.max(a, b);
return Math.max(temp, c);
}
public static int maxsum(int arr[]) {
return maxSubSum(arr,0,arr.length-1);
}
}
运行结果: