• 01-复杂度1 最大子列和问题


    给定KK个整数组成的序列{ N_1N1​​, N_2N2​​, ..., N_KNK​​ },“连续子列”被定义为{ N_iNi​​, N_{i+1}Ni+1​​, ..., N_jNj​​ },其中 1 le i le j le K1ijK。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

    本题旨在测试各种不同的算法在各种数据情况下的表现。各组测试数据特点如下:

    • 数据1:与样例等价,测试基本正确性;
    • 数据2:102个随机整数;
    • 数据3:103个随机整数;
    • 数据4:104个随机整数;
    • 数据5:105个随机整数;

    输入格式:

    输入第1行给出正整数KK (le 100000100000);第2行给出KK个整数,其间以空格分隔。

    输出格式:

    在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。

    输入样例:

    6
    -2 11 -4 13 -5 -2
    

    输出样例:

    20




    ---------------------------------------------
    这里给出四个算法

    算法1:空间复杂度 0(n^3)
     1 int maxSubList1(int a[], int n)
     2 {
     3     int max = 0;
     4     int i,j,k;
     5     int thisSum;
     6     for (i = 0; i < n; ++i)
     7     {
     8         for(j = i; j < n; ++j)
     9         {
    10             thisSum = 0;
    11             for(k = i; k < j; k++)
    12                 thisSum += a[k];
    13             if(thisSum > max)
    14                 max = thisSum;
    15         }
    16     }
    17     return max;
    18 }

    算法2:复杂度0(n^2)

    int maxSubList2(int a[], int n)
    {
        int max = 0;
        int i,j;
        int thisSum;
        for (i = 0; i < n; ++i)
        {
            thisSum = 0;
            for(j = i; j < n; ++j)
            {
                thisSum += a[j];
                if(max < thisSum)
                    max = thisSum;
            }
        }
        return max;
    }

    算法3 ,分而治之 ,复杂度O(Nlogn)

    说实话,这个算法,怎么明白,听陈约姥姥讲的,听明白了算法,不知道怎么实现

    // 求ab的最大值
    int max(int a, int b)
    {
        return a > b ? a : b;
    }
    
    // 第三个算法
    int maxSubList3(int a[], int left, int right)
    {
        // 如果只有一个数
        int i;
        int center = (left + right) / 2; //中点
        int leftMaxSum, rightMaxSum, lrMaxSum;
    
        int maxLeftSum = 0;  
        int leftSum = 0;   //跨越边界的左端值最大
    
        int maxRightSum = 0;
        int rightSum = 0;
    
        if(left == right)
            return a[left];
        leftMaxSum = maxSubList3(a, left, center);// 整个出现在输入数据的左半部的最大子序列求和 
        rightMaxSum = maxSubList3(a, center+1, right);// 整个出现在输入数据的右半部的最大子序列求和 
        lrMaxSum = max(leftMaxSum, rightMaxSum); //计算左右两个子序列求和结果的最大值
    
        // 横跨左右两个部分的最大子序列求和
    
        //从center向左处理左半边  
        
        for (i = center; i >= left; i--)
        {  
            leftSum += a[i];  
            maxLeftSum = max(maxLeftSum, leftSum);  
        } 
    
        for (i = center+1; i <= right; ++i)
        {
            rightSum =+ a[i];
            maxRightSum = max(maxRightSum, rightSum);
        }
        return max(lrMaxSum, maxLeftSum + maxRightSum);
    }

    算法4,在线测试,所谓在线就是一次便利,随搞随用 复杂度O(N)

    这个算法还是比较好理解的

    int maxSubList4(int A[], int N )  
    {   int ThisSum, MaxSum;
        int i;
        ThisSum = MaxSum = 0;
        for( i = 0; i < N; i++ ) {
            ThisSum += A[i]; /* 向右累加 */
                if( ThisSum > MaxSum )
                    MaxSum = ThisSum; /* 发现更大和则更新当前结果 */
                else if( ThisSum < 0 ) /* 如果当前子列和为负 */
                    ThisSum = 0; /* 则不可能使后面的部分和增大,抛弃之 */
        }
        return MaxSum;  
    }

    最后提交的程序

    #include "stdio.h"
    #define size 100000
    
    int maxSubList1(int a[], int n)
    {
        int max = 0;
        int i,j,k;
        int thisSum;
        for (i = 0; i < n; ++i)
        {
            for(j = i; j < n; ++j)
            {
                thisSum = 0;
                for(k = i; k < j; k++)
                    thisSum += a[k];
                if(thisSum > max)
                    max = thisSum;
            }
        }
        return max;
    }
    
    int maxSubList2(int a[], int n)
    {
        int max = 0;
        int i,j;
        int thisSum;
        for (i = 0; i < n; ++i)
        {
            thisSum = 0;
            for(j = i; j < n; ++j)
            {
                thisSum += a[j];
                if(max < thisSum)
                    max = thisSum;
            }
        }
        return max;
    }
    
    // 求ab的最大值
    int max(int a, int b)
    {
        return a > b ? a : b;
    }
    
    // 第三个算法
    int maxSubList3(int a[], int left, int right)
    {
        // 如果只有一个数
        int i;
        int center = (left + right) / 2; //中点
        int leftMaxSum, rightMaxSum, lrMaxSum;
    
        int maxLeftSum = 0;  
        int leftSum = 0;   //跨越边界的左端值最大
    
        int maxRightSum = 0;
        int rightSum = 0;
    
        if(left == right)
            return a[left];
        leftMaxSum = maxSubList3(a, left, center);// 整个出现在输入数据的左半部的最大子序列求和 
        rightMaxSum = maxSubList3(a, center+1, right);// 整个出现在输入数据的右半部的最大子序列求和 
        lrMaxSum = max(leftMaxSum, rightMaxSum); //计算左右两个子序列求和结果的最大值
    
        // 横跨左右两个部分的最大子序列求和
    
        //从center向左处理左半边  
        
        for (i = center; i >= left; i--)
        {  
            leftSum += a[i];  
            maxLeftSum = max(maxLeftSum, leftSum);  
        } 
    
        for (i = center+1; i <= right; ++i)
        {
            rightSum =+ a[i];
            maxRightSum = max(maxRightSum, rightSum);
        }
        return max(lrMaxSum, maxLeftSum + maxRightSum);
    }
    
    int maxSubList4(int A[], int N )  
    {   int ThisSum, MaxSum;
        int i;
        ThisSum = MaxSum = 0;
        for( i = 0; i < N; i++ ) {
            ThisSum += A[i]; /* 向右累加 */
                if( ThisSum > MaxSum )
                    MaxSum = ThisSum; /* 发现更大和则更新当前结果 */
                else if( ThisSum < 0 ) /* 如果当前子列和为负 */
                    ThisSum = 0; /* 则不可能使后面的部分和增大,抛弃之 */
        }
        return MaxSum;  
    }
    int main(int argc, char const *argv[])
    {
        int i, n, a[size];
        while(scanf("%d", &n) != EOF)
        {
            for (i = 0; i < n; ++i)
            {
                scanf("%d", &a[i]);
            }
            printf("%d
    ", maxSubList4(a, n));
        }
        return 0;
    }
  • 相关阅读:
    Linux 用C语言实现简单的shell(1)
    线性回归 Linear regression(4) 局部加权回归
    线性回归 Linear regression(3) 线性回归的概率解释
    线性回归 Linear regression(2)线性回归梯度下降中学习率的讨论
    线性回归 Linear regression(1)线性回归的基本算法与求解
    超多JavaASP.NETPHPoracleandroidiphoneVC++项目实战视频教程免费下载
    struct 和 typedef struct
    soj1200- 简单的等式 (素数打表,找因子)
    soj1209- 最短的距离(精度问题)
    快排
  • 原文地址:https://www.cnblogs.com/hello-lijj/p/6506758.html
Copyright © 2020-2023  润新知