最大子数组和问题

问题定义:

    求数组A中一个连续的和最大的子数组。比如数组[4,5,-6,7,-3,1]的最大子数组是[4,5,-6,7],和为10。

 

解法一:分治法

    可以把问题转化成求两个子数组的最大子数组问题。令mid为数组A[low, high]的中间位置,则A[low, high]的最大子数组所处的位置存在如下三种情况:

1、完全位于A[low, mid]之中

2、完全位于A[mid+1, high]之中

3、横跨中点mid

对于1、2两种情况相当于将问题的规模缩小为原来的一半,因此只需要递归求解即可。第3种情况需要单独考虑。

首先可知横跨中点mid的子数组中一定包含元素A[mid],则我们可以将第3种情况一分为二,任何横跨中点的子数组都由两个子数组A[i,..,mid]和A[mid+1,..,j]组成,所以我们可以以中点mid为界,向两边寻找两个最大子数组A[i,..,mid]和A[mid+1,..,j],然后再将其合并即可。寻找横跨中点的最大子数组代码如下:

 1 public int[] findCrossMaxSubArray(int[] A, int low, int mid, int high) {
 2     int curSum, leftSum, rightSum;
 3     curSum = leftSum = rightSum = 0;
 4     int i,j, begin = 0, end = 0;
 5     for (i = mid; i >= low; i--) {
 6         curSum += A[i];
 7         if (curSum > leftSum) {
 8             leftSum = curSum;
 9             begin = i;
10         }
11     }
12     for (j = mid + 1, curSum = 0; j <= high; j++) {
13         curSum += A[j];
14         if (curSum > rightSum) {
15             rightSum = curSum;
16             end = j;
17         }
18     }
19     return new int[]{begin, end, leftSum+rightSum};
20 }

 下标i标识的是子数组的起始位置,j标识的是终止位置,leftSum和rightSum分别存储两个子数组中的最大的和。

    解决了以上问题,那么求数组A[low, high]的最大子数组就迎刃而解了,代码如下:

 1 public static int[] findMaxSubArray(int[] A, int low, int high) {
 2     // base case:只有一个元素
 3     if (low == high) {
 4         return new int[] {low, high, A[low]};
 5     } else {
 6         int mid = (low + high) >>> 1;
 7         // 分别求出A[low, mid], A[mid+1, high], 以及横跨中点
 8         // 的三个最大子数组。
 9         int[] left = findMaxSubArray(A, low, mid);
10         int[] right = findMaxSubArray(A, mid+1, high);
11         int[] cross = findCrossMaxSubArray(A, low, mid, high);
12         // 返回三者中和最大的一个
13         int leftSum = left[2], rightSum = right[2], crossSum = cross[2];
14         if (leftSum >= rightSum && leftSum >= crossSum) {
15             return left;
16         } else if (rightSum >= leftSum && rightSum >= crossSum) {
17             return right;
18         } else {
19             return cross;
20         }
21         
22     }
23 }

 

 

posted @ 2013-10-08 22:18  StrikeW  阅读(413)  评论(0编辑  收藏  举报