求最大子序列之和

摘要:给出一个序列,求出其中连续的子序列中和最大的一个。(如 1 3 -5 2 -1 4 5)最大子序列之和是2 -1 4 5
基本思路:
【1】最简单的办法就是遍历一边序列,用变量Thissum记录遍历过的元素之和,当Thisum>0时,继续相加.若Thisum < 0,令Thisum = 0,吧下一个元素作为新的子序列的开头.同时检测所有Thissum的最大值.这个算法很容易理解:因为如果Thissum>0,那么加上后面的元素有可能产生最大值,但如果Thissum<0,那么包括它一定不会产生最大值.
【2】尽管方法【1】的效率是O(N),而且编程简单,但是适用范围只限于加法或者减法.这里还有一种更通用的方法,分治算法。
基本思路:将该序列分为2部分,求出左边与右边最大和,然后从中间开始向两边遍历找出经过中间的最大子序列,将三个值进行比较。对于两部分的也是递归的计算,时间界是O(NlogN);
推算时间界
T(N) = 2T(2/N) + O(N);不妨令N = 2^k,T(1) = 1;
T(2^k) = 2T(2^(k-1)) + 2^k,
->T(2^k)/2^k = T(2^(k-1))/(2^(k-1)) + 1;
所以T(2^k)/2^k = K;T(N) = NlogN;

#include "stdafx.h"
#include "stdlib.h"
#define Positive 0
#define Negative 1

int Max3(int a, int b, int c)
{
     a = (a>b?a:b);
    return (a>c?a:c);
}
//求最大子序列之和
static int Maxsub(const int A[],int Left, int Right)
{
    int Max_Left,Max_Right;
    int center;;
    int LeftBodersum,RightBodersum;
     int Max_LeftBodersum, Max_RightBodersum;

    if (Left == Right)//处理基准情况
    {
        if (A[Left]>0)
            return A[Left];
        else
            return 0;
    }
    center = (Left + Right)/2;
    Max_Left = Maxsub(A,Left,center);
    Max_Right = Maxsub(A,center+1,Right);

    LeftBodersum = 0;
    RightBodersum = 0;
    Max_LeftBodersum = 0;
    Max_RightBodersum = 0;
    for (int i = center;i>=Left;i--)
    {
        LeftBodersum +=A[i];
        if (LeftBodersum >= Max_LeftBodersum)
            Max_LeftBodersum = LeftBodersum;
    }

    for (int i = center+1;i<=Right;i++)
    {
        RightBodersum +=A[i];
        if (RightBodersum >= Max_RightBodersum)
            Max_RightBodersum = RightBodersum;
    }

    return Max3(Max_Left,Max_Right,Max_LeftBodersum+Max_RightBodersum);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值