最大连续子序列和及其起始位置(未测试)

/******************************

问题描述:求一个序列中的最大连续子序列和以及起始位置。若全为负数,则返回0。

*******************************/

 

 

int start, end;

start = end = 0;

/******************************

算法名称:枚举法

简述:列举所有可能的序列,并求和。前缀相同的序列重复求和,

      违背了“同一个数最多计算一次”的原则,导致复杂度上升。

复杂度分析:T(N) =  =

时间复杂度:O()

******************************/

int Sum1(const int A[], int n)

{

    int i, j, k;

         int start, end;

    int ThisSum, MaxSum;

   

         MaxSum = 0;

    for(i = 0; i < n; i++) /* 确定序列的起始索引 */

        for(j = i; j < n; j++){ /* 确定序列的终止索引 */

            ThisSum = 0;

            for(k = i; k <= j; k++)  /* 遍历A[i]~A[j] */

                ThisSum += A[k];

            if(ThisSum > MaxSum){

                MaxSum = ThisSum;

                                     start = i;

                                     end = j;

                            }

        }

         return MaxSum;

}

 

/*****************************

算法名称:枚举法

简述:列举所有可能的序列。但在求和时,避免重复求和,复杂度降低。

算法分析:T(N) =  = ()/2

时间复杂度:O()

 

******************************/

int Sum2(const int A[], int n)

{

         int i, j;

         int ThisSum, MaxSum;

 

         MaxSum = 0;

         for(i = 0; i < n; i++){

                   ThisSum = 0;

                   for(j = i; j < n; j++){

                            ThisSum += A[j];        /* S(j) = A[j] + S(j-1) */

                            if(ThisSum > MaxSum){

                                     MaxSum = ThisSum;

                                     start = i;

                                     end = j;

                            }

                   }

         }

         return MaxSum;

}

 

/******************************

算法名称:分治递归法

简述:①每个序列的最大子序列有三个可能的位置:1、序列左半部;2、序列右半部;3、跨越序列左右半部分

           1、左半部,用递归求最大子序列和

           2、右半部,用递归求最大子序列和

           3、从中间元素开始,分别求左半部和右半部最大子序列和,然后求和

           ②base case:当所求序列只有一个元素时,若为正数,则返回该数,否则返回0。

           ③返回三个位置中最大的和。

复杂度分析:T(N) = 2T(N/2) + O(N)

时间复杂度:O(NlogN)

*******************************/

int Max3(int a, int b, int c)

{

         if(b > a)

                   a = b;

         if(c > a)

                   a = c;

         return a;

}

 

int SumSub3(const int A[], int left, int right)

{

         int center, i;

         int MaxLeftSum, MaxRightSum;

         int MaxLeftBorderSum, MaxRightBorderSum;

         int LeftBorderSum, RightBorderSum;

 

         if(left == right){               /* base case */

                   if(A[left] > 0)

                            return A[left];

                   else

                            return 0;

         }

 

         center = (left + right) / 2;

         MaxleftSum = SumSub3(A, left, center);      /* 左半部分的最大子序列 */

         MaxRightSum = SumSub3(A, center+1, right);  /* 右半部分的最大子序列 */

 

         MaxLeftBorderSum = 0; LeftBorderSum = 0;    /* 跨左右两部分的最大子序列的左半部分 */

         for(i = center; i >= 0; i--){

                   LeftBorderSum += A[i];

                   if(LeftBorderSum > MaxLeftBorderSum){

                            MaxLeftBorderSum = LeftBorderSum;

                            start = i;

                   }

         }

 

         MaxRightBorderSum = 0; RightBorderSum = 0; /* 跨左右两部分的最大子序列的右半部分 */

         for(i = center+1; i <= right; i++){

                   RightBorderSum += A[i];

                   if(RightBorderSum > MaxRightBorderSum){

                            MaxRightBorderSum = RightBorderSum;

                            end = i;

                   }

         }

 

         return Max3(MaxLeftBorderSum + MaxRightBorderSum, MaxleftSum, MaxRightSum);    /* 返回三种子序列中的最大值 */

}

 

int Sum3(const int A[], int n)

{

         return SumSub3(A,0, n-1);

}

 

/*********************************

算法名称:线性联机算法

简述:重要思想:任何和为负数的子序列都不可能是最大子序列的前缀。

若A[i] 为负数,则A[i] 不可能是最大子序列的前缀,同理,即若A[i] 到A[j]的j-i+1个元素的和为负数,则应将其抛弃,重新求和。

在A[j]之前可能有最大和,会保存在MaxSum中,而ThisSum则重新求和(求和)。

复杂度分析:时间复杂度为O(N),线性。

                            每次读取一个元素后,不需要存储,直接加到ThisSum上。

                            而且此算法在任何时刻都能对已读取数据给出当前数据的解。联机算法。

常量空间线性时间的联机算法几乎是完美的算法。

**********************************/

int Sum4(const 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;

                            end = i;

                   }

                   else if(ThisSum < 0)   /* 当前子序列的和为负,则应重新求和 */

                            ThisSum = 0;

                            start = i+1;

         }

 

         return MaxSum;

}

转载于:https://www.cnblogs.com/ithink/p/max_subsequence_sum.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值