一个数组的最大子数组和可能存在于三种情况中:
1. 该数组的左子数组中
2.该数组的右子数组中
3.可能横跨左右子数组
所以,我们可以将问题分解成一个个的子问题,其中情况1和2可用递归求解,而情况3则需要计算
s1=max{} (1 <= i <= n/2), s2=max{} (n/2+1 <= j <=n),其中情况3中s1必然包含了,
s2中必然包含了,因为情况3跨越了左右子数组。s1 + s2为情况3的最大子数组。
/* * 利用分治法求最大子数组问题 */ public class TestOne { public static int leftFlag; //负责记录最大子数组和的开始下标 public static int rightFlag; //负责记录最大子数组和的结束下标 //求最大子数组跨越了两个数组的情况 public static int midArray(int[] a,int low,int mid,int high) { // 求low...mid之间的最大数组和 int leftSum = -10000; int sum = 0; for(int i = mid;i>=low;i--) { sum += a[i]; if(sum > leftSum) { leftSum = sum; leftFlag = i; } } //求mid+1...high之间的最大数组和 int rightSum = -10000; sum = 0; for(int i = mid+1;i<=high;i++) { sum += a[i]; if(sum > rightSum) { rightSum = sum; rightFlag = i; } } return leftSum + rightSum; } public static int subArray(int[] a,int low,int high) { if(high==low) return a[low]; int mid = (low + high) / 2; int leftSum = subArray(a,low,mid); //求出左边数组的最大子数组和 int rightSum = subArray(a,mid+1,high); //求出右边数组的最大子数组和 int midSum = midArray(a,low,mid,high); //求出跨越左右两个数组的最大子数组和 if(leftSum > rightSum && leftSum > midSum) return leftSum; else if(rightSum > leftSum && rightSum > midSum) return rightSum; else return midSum; } public static void main(String[] args) { int[] a = {13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7}; System.out.println(subArray(a,0,a.length-1)); System.out.println(leftFlag + " " + rightFlag); } }