• 最大子序列求和问题


    最大子序列求和问题

    问题描述

    给定整数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!
    ");
            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!
    ");
            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
    ", max_sub_sum(A, sizeof(A)/sizeof(int)));
        printf("max_sub_sum = %d
    ", max_sub_sum2(A, sizeof(A)/sizeof(int)));
        printf("max_sub_sum = %d
    ", max_sub_sum3(A, sizeof(A)/sizeof(int)));
        printf("max_sub_sum = %d
    ", max_sub_sum4(A, sizeof(A)/sizeof(int)));
    
        return 0;
    }
  • 相关阅读:
    GitHub上创建项目
    html5的标签中,哪些是行内元素,哪些是块级元素。
    盒子模型及其他的层次结构关系
    二维码生成
    SSH整合笔记
    Spring回顾
    struts2 测试错题解析
    Java Script基础
    Java OOP考试错题分析
    接口的用法及注意点
  • 原文地址:https://www.cnblogs.com/born2run/p/9581333.html
Copyright © 2020-2023  润新知