最大子序列求和问题

最大子序列求和问题

问题描述

给定整数A1A2,…, AN(可能有负数),求k=ijAk的最大值(为方便起见,如果所有整数均为负数,则最大子序列和为0)。

求解

算法1:

int max_sub_sum(const int A[], int N)
{
    int sum, maxsum,i,j,k;
    maxsum = 0;
    for(i = 0; i<N; i++){
        for(j = i; j<N; j++){
            //求A[i]~A[j]的和
            sum = 0;
            for(k = i; k<j; k++){
                sum += A[k];
            }
            if(sum > maxsum)
                maxsum = sum;
        }
    }

    return maxsum;
}

算法1的时间复杂度为O(N3)

算法2:

int max_sub_sum2(const int A[], int N)
{
    int sum, maxsum, i, j;
    maxsum = 0;
    for(i = 0; i<N; i++){
        sum = 0;
        for(j = i; j<N; j++){
            sum += A[j];
            if(sum > maxsum){
                maxsum = sum;
            }
        }
    }

    return maxsum;
}

算法2的复杂度为O(N3),与算法1相比,算法2减少了一个内层循环

算法3

int maxsubsum(const int A[], int left, int right)
{
    //采用分治法求解
    if(left > right){
        printf("error: left>right!\n");
        return -1;
    } else if(left == right) {
        if(A[left]>=0) {
            return A[left];
        } else {
            return 0;
        }
    } else {
        int maxleftsum, maxrightsum, maxleftborder, maxrightborder, maxcrosssum, tmpsum;
        int center, i;
        center = (left+right)/2;
        maxleftsum = maxsubsum(A, left, center);
        maxrightsum = maxsubsum(A, center+1, right);

        tmpsum = maxleftborder = 0;
        for(i = center; i>=left; i--){
            tmpsum += A[i];
            if(tmpsum > maxleftborder) {
                maxleftborder = tmpsum;
            }
        }
        tmpsum = maxrightborder = 0;
        for(i = center+1; i<=right; i++) {
            tmpsum += A[i];
            if(tmpsum > maxrightborder) {
                maxrightborder = tmpsum;
            }
        }
        maxcrosssum = maxleftborder+maxrightborder;

        if(maxcrosssum >= maxleftsum && maxcrosssum >= maxrightsum)
            return maxcrosssum;
        if(maxleftsum >= maxcrosssum && maxleftsum >= maxrightsum)
            return maxleftsum;
        if(maxrightsum >= maxcrosssum && maxrightsum >= maxleftsum)
            return maxrightsum;
    }
}
int max_sub_sum3(const int A[], int N)
{
    return maxsubsum(A, 0, N-1);
}

算法3用了分治法来求解,以序列的中间为分界线,最大子序列要么再左边一半,要么再右边一半,要么穿过中间,只要分别求左边一半最大子序列、右边一半最大子序列和穿过中间爱的最大子序列,最后从它们之间选出最大的即是整个序列的最大子序列,该分治算法的时间复杂度为O(NlogN)

算法4

int max_sub_sum4(const int A[], int N)
{
    int sum, maxsum, i;
    sum = maxsum = 0;
    for(i = 0;i<N; i++){
        sum += A[i];
        if(sum > maxsum) {
            maxsum = sum;
        } else if (sum < 0) {
            sum = 0;
        }
    }

    return maxsum;
}

算法4的时间复杂度为O(N),该算法只要读一遍输入序列就可以算出最大子序列和

实验

#include <stdio.h>
#include <stdlib.h>

int max_sub_sum(const int A[], int N)
{
    int sum, maxsum,i,j,k;
    maxsum = 0;
    for(i = 0; i<N; i++){
        for(j = i; j<N; j++){
            //求A[i]~A[j]的和
            sum = 0;
            for(k = i; k<j; k++){
                sum += A[k];
            }
            if(sum > maxsum)
                maxsum = sum;
        }
    }

    return maxsum;
}

int max_sub_sum2(const int A[], int N)
{
    int sum, maxsum, i, j;
    maxsum = 0;
    for(i = 0; i<N; i++){
        sum = 0;
        for(j = i; j<N; j++){
            sum += A[j];
            if(sum > maxsum){
                maxsum = sum;
            }
        }
    }

    return maxsum;
}

int maxsubsum(const int A[], int left, int right)
{
    //采用分治法求解
    if(left > right){
        printf("error: left>right!\n");
        return -1;
    } else if(left == right) {
        if(A[left]>=0) {
            return A[left];
        } else {
            return 0;
        }
    } else {
        int maxleftsum, maxrightsum, maxleftborder, maxrightborder, maxcrosssum, tmpsum;
        int center, i;
        center = (left+right)/2;
        maxleftsum = maxsubsum(A, left, center);
        maxrightsum = maxsubsum(A, center+1, right);

        tmpsum = maxleftborder = 0;
        for(i = center; i>=left; i--){
            tmpsum += A[i];
            if(tmpsum > maxleftborder) {
                maxleftborder = tmpsum;
            }
        }
        tmpsum = maxrightborder = 0;
        for(i = center+1; i<=right; i++) {
            tmpsum += A[i];
            if(tmpsum > maxrightborder) {
                maxrightborder = tmpsum;
            }
        }
        maxcrosssum = maxleftborder+maxrightborder;

        if(maxcrosssum >= maxleftsum && maxcrosssum >= maxrightsum)
            return maxcrosssum;
        if(maxleftsum >= maxcrosssum && maxleftsum >= maxrightsum)
            return maxleftsum;
        if(maxrightsum >= maxcrosssum && maxrightsum >= maxleftsum)
            return maxrightsum;
    }
}
int max_sub_sum3(const int A[], int N)
{
    return maxsubsum(A, 0, N-1);
}

int max_sub_sum4(const int A[], int N)
{
    int sum, maxsum, i;
    sum = maxsum = 0;
    for(i = 0;i<N; i++){
        sum += A[i];
        if(sum > maxsum) {
            maxsum = sum;
        } else if (sum < 0) {
            sum = 0;
        }
    }

    return maxsum;
}

int main()
{
    int A[]={-2, 11, -4, 13, -5, -2};

    printf("max_sub_sum = %d\n", max_sub_sum(A, sizeof(A)/sizeof(int)));
    printf("max_sub_sum = %d\n", max_sub_sum2(A, sizeof(A)/sizeof(int)));
    printf("max_sub_sum = %d\n", max_sub_sum3(A, sizeof(A)/sizeof(int)));
    printf("max_sub_sum = %d\n", max_sub_sum4(A, sizeof(A)/sizeof(int)));

    return 0;
}
posted @ 2018-06-23 17:30  main_c  阅读(339)  评论(0编辑  收藏  举报