zoukankan      html  css  js  c++  java
  • 最大子列和问题

    问题描述:给定K个整数组成的序列{ N1​​, N2​​, ..., NK​​ },“连续子列”被定义为{ Ni​​, Ni+1​​, ..., Nj​​ },其中 1ijK。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

    1.穷举法:时间复杂度O(n^3)

    穷举法,计算了所有可能性,时间复杂度O(n^3)。

     1 int MaxSubseqSum1(int a[],int size)
     2 {
     3     int ThisSum,MaxSum=0;
     4     for(int i = 0;i < size;i++)
     5         for(int j = i;j < size;j++)
     6         {    
     7             ThisSum = 0;
     8             for(int k = i;k <= j;k++)
     9                 ThisSum += a[k];
    10             if(MaxSum < ThisSum)
    11                 MaxSum = ThisSum;
    12         }
    13     return MaxSum;
    14 }

    2.算法二:时间复杂度O(n^2)

    在穷举法的基础上略有改进,少了一重for循环,效率有所提高,代码简单易懂。

    int MaxSubseqSum2(int a[],int size)
    {
        int ThisSum,MaxSum=0;
        for(int i = 0;i < size;i++)
        {
            ThisSum = 0;
            for(int j = i;j < size;j++)
            {
                ThisSum += a[j];
                if(MaxSum < ThisSum)
                    MaxSum = ThisSum;
            }    
        }
        return MaxSum;
    }

    3.分而治之:时间复杂度O(nlogn)

    采用递归的思想。最大子列和有三种情况,左边最大子列和,右边最大子列和,跨越中间的最大子列和,取三之大者。递归到最后即,两个数,比较左数右数或他们的和,取大。

     1 //分而治之 
     2 int MaxSubseqSum3(int a[],int size)
     3 {
     4     return MaxSum(a,0,size-1);
     5 }
     6 
     7 int MaxSum(int a[],int left,int right)
     8 {
     9     if(left == right)
    10         return a[left] > 0 ? a[left] : 0;
    11     int center = (left + right) / 2; 
    12     int MaxLeftSum = MaxSum(a,left,center);
    13     int MaxRightSum = MaxSum(a,center+1,right);
    14     //求左边界最大值 
    15     int Centerto_Left = 0,MaxSum_Centerto_Left = 0;
    16     for(int i = center;i >= left;i--){
    17         Centerto_Left += a[i];
    18         if(MaxSum_Centerto_Left < Centerto_Left)
    19             MaxSum_Centerto_Left = Centerto_Left;
    20     }
    21     // 求右边界最大值
    22     int Centerto_Right = 0,MaxSum_Centerto_Right = 0;
    23     for(int i = center+1;i <= right;i++){
    24         Centerto_Right += a[i];
    25         if(MaxSum_Centerto_Right < Centerto_Right)
    26             MaxSum_Centerto_Right = Centerto_Right;
    27     }
    28     return MaxSum3(MaxLeftSum,MaxRightSum,MaxSum_Centerto_Left + MaxSum_Centerto_Right);
    29 }
    30 int MaxSum3(int a,int b,int c)
    31 {
    32     return (a>b?a:b)>c?(a>b?a:b):c; 
    33 }

     4.在线处理:时间复杂度O(n)

    在线处理的规则是,从头开始求子列和,并记录当前最大子列和,若当前子列和为负,则抛弃之。代码很清楚的说明了这一规则。

    个人认为在线处理的理解核心:当前子列和若为正,总有可能使之后的子列和变大的。如果当前子列和为负,则不可能是后面的子列和变大,所以抛弃。

     1 //在线处理
     2 int MaxSubseqSum4(int a[],int size)
     3 {
     4     int ThisSum=0,MaxSum=0;
     5      for(int i = 0;i < size;i++){
     6          ThisSum += a[i];
     7         if(MaxSum < ThisSum)
     8              MaxSum = ThisSum;
     9         else if(ThisSum < 0)
    10             ThisSum = 0;
    11     }
    12     return MaxSum;
    13 }

                                                          整理自Mooc陈越 、何钦铭数据结构课程

  • 相关阅读:
    php排序算法-冒泡排序
    Mac安装java JDK
    mysql索引简单记录一下
    Mac 通过 pecl安装 redis 扩展
    Mac通过pecl安装swool时遇到的坑(root + openssl)
    php获取两个日期的之间的日期信息,返回数组
    2021.4.9训练
    王道数据结构代码:双向链表的操作
    王道数据结构代码:单链表的操作
    PTA 7-1 大炮打蚊子 (15 分)
  • 原文地址:https://www.cnblogs.com/kuotian/p/4825603.html
Copyright © 2011-2022 走看看