分治——最大子数组问题

样例:A={13,-3,-25,20,-3,-16,-23,18,20,-7,12,-15,-22,15,-4,7},最大子数组为A[7~10],和为43。

思路:先求出跨中点的最大子数组,再递归的求解左边一半的最大子序列和右边一半的最大子序列,以此类推。

 伪代码:

FIND_MAX_CROSSING_SUBARRAY(A,low,mid,high)
left_sum=A[mid]        //注意是left_sum=A[mid]不是left_sum=负无穷,书上错了!!
sum=0;
for i=mid downto low        //第一次不执行这句!!因为mid==low==0!!
    sum=sum+A[i]
    if sum>left_sum
        left_sum=sum
        max_left=i
right_sum=A[mid+1]        //一样,书上错了!!
sum=0
for i=mid+1 to high                    //注意!这里是mid+1
    sum=sum+A[i]
    if sum>right_sum
        right_sum=sum
        max_right=i
return(max_left,max_right,left_sum+right_sum)

FIND_MAX_SUBARRAY(A,low,high)
if high==low
    return(low,high,A[low])
else
mid=[(low+high)/2]
(left_low,left_high,left_sum)= FIND_MAX_SUBARRAY(A,low,mid)
(right_low,right_high,right_sum)= FIND_MAX_SUBARRAY(A,mid+1,high)
(cross_low,cross_high,cross_sum)= FIND_MAX_CROSSING_SUBARRAY(A,low,mid,high)
if left_sum>=right_sum and left_sum>=cross_sum
    return(left_low,left_high,left_sum)
else if right_sum>=left_sum and right_sum>=cross_sum
    return(right _low, right _high, right _sum)
else return(cross_low,cross_high,cross_sum)

C语言代码(附调试):

#include<stdio.h>
int FIND_MAX_CROSSING_SUBARRAY(int* A, int low, int mid, int high);
int FIND_MAX_SUBARRAY(int* A, int low, int high);
int main()
{
    int A[16] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -15, -22, 15, -4, 7 };
    int  sum;
    sum=FIND_MAX_SUBARRAY(A,0,15);
    printf("%d\n", sum);
    printf("hello..");
    system("pause");
    return 0;
}
int FIND_MAX_SUBARRAY(int* A, int low, int high)
{
    int mid, left_sum, right_sum, cross_sum;
    if (high == low)
        return(low, high, A[low]);
    else
    {
        mid = (low + high) / 2;
//        printf("mid=%d\n", mid);
     left_sum= FIND_MAX_SUBARRAY(A, low, mid);
//     printf("left_sum=%d\n", left_sum);
     right_sum = FIND_MAX_SUBARRAY(A, mid+1, high);
//     printf("right_sum=%d\n", right_sum);
    cross_sum = FIND_MAX_CROSSING_SUBARRAY(A, low, mid, high);
//    printf("low=%d\tmid=%d\thigh=%d\tcross_sum=%d\n", low,mid,high,cross_sum);
    }
        
    if (left_sum >= right_sum && left_sum >= cross_sum)
        return left_sum;
    else if (right_sum >= left_sum && right_sum >= cross_sum)
        return right_sum;
    else
        return cross_sum;
}

int FIND_MAX_CROSSING_SUBARRAY(int* A, int low, int mid, int high)
{
    int  left_sum, right_sum;
     left_sum = A[mid];
    int sum = 0;
    int i;
        for (i = mid; i >low; i--)
        {
            sum = sum + A[i];
                if (sum > left_sum)
                {
                    left_sum = sum;
                }
//                printf("cross_left_sum=%d\n", left_sum);
        }
     right_sum = A[mid+1];
        sum = 0;        
        for (i = mid+1; i <high; i++)
        {
            sum = sum + A[i];
                if (sum > right_sum)
                {
                    right_sum = sum;
                }
        }
//        printf("cross_left_sum=%d\tcross_right_sum=%d", left_sum, right_sum);
        return left_sum + right_sum;
}

 

posted @ 2018-03-16 09:09  Alexadar  阅读(217)  评论(0)    收藏  举报