求下面序列的最大子序列和:
4 -3 5 2 -1 2 6 -2
对于这个例子,最大子序列和可能在三处出现。
1.整个出现在输入数据的左半部。
2.整个出现在输出数据的右半部。
3.跨越输入数据的中部从而位于左右两半部分之中。
前两种情况可以递归求解。第三种情况的最大和可以通过求出前半部分(包含前半部分最后一个元素)的最大和以及后半部分(包含后半部分第一个元素)的最大和而得到。此时将这两个和相加。作为一个例子。考虑下列输出:
前半部分 | 后半部分 |
4 -2 5 -2 | -1 2 6 -2 |
其中前半部分的最大子序列和为6(从元素A1到A3)而后半部分的最大子序列和为8(从元素A6到A7)。
前半部分包含其最后一个元素的最大和是4(从元素A1到A4),而后半部分包含其第一个元素的最大和是7(从元素A5到A7)。因此,横跨这两部分且通过中间的最大和为4+7=11(从A1到A7)。
代码如下:
public class Main {
public static void main(String[] args){
int a[]={4,-3,5,-2,-1,2,6,-2};
System.out.println(maxSumRec(a,0,a.length-1));
}
private static int maxSumRec(int[] a, int left, int right) {
if (left==right)
{
if (a[left]>0)
return a[left];
else
return 0;
}
int center = (left+right)/2;
int maxLeftSum = maxSumRec(a,left,center);
int maxRightSum = maxSumRec(a,center+1,right);
int maxLeftBorderSum=0,leftBorderSum=0;
for (int i = center;i>=left;i--)
{
leftBorderSum+=a[i];
if (leftBorderSum>maxLeftBorderSum)
{
maxLeftBorderSum=leftBorderSum;
}
}
int maxRightBorderSum=0,RightBorder=0;
for (int i = center+1;i<=right;i++)
{
RightBorder+=a[i];
if (RightBorder>maxRightBorderSum)
{
maxRightBorderSum=RightBorder;
}
}
return max3(maxLeftSum,maxRightSum,maxLeftBorderSum+maxRightBorderSum);
}
private static int max3(int num1,int num2,int num3) {
int max =0;
int temp1 = num1>num2?num1:num2;
max = temp1>num3?temp1:num3;
return max;
}
}
运行结果:
11
这个分治法我哥假期里面给我讲过一下原理,但是并不知道该如何去写代码。。。还是从书上看的,现在成功掌握了。