最大子序列求和

47 篇文章 0 订阅
40 篇文章 0 订阅

问题:给定整数A1,A2,....  (可能有负数),求最大的连续子序列

第一种方法:

暴力求解

int Sum1(const int a[],int n)
{
    int maxSum = a[0];
    for(int i = 0;i < n ;i++)
        for(int j = i;j < n;j++)
        {
                int temSum = 0;
                for(int k = i;k <= j;k++)
                    temSum += a[k];
                if(temSum > maxSum)maxSum = temSum;
        }
        return maxSum;
}

第二种

暴力求解略微改进

int Sum2(const int a[], int n)
{
    int maxSum = a[0];
    for(int i = 0;i < n;i++)
    {
        int tem = 0;
        for(int j = i;j < n;j++)
        {
            tem += a[j];
            if(tem > maxSum)maxSum = tem;
        }
    }
    return maxSum;
}

第三种 

分治方法

int Sum3Tem(const int a[],int left,int right)
{
    int MaxLeftSum,MaxRightSum;
    int MaxLeftBorderSum,MaxRightBorderSum;
    int LeftBorder,rightBorder;
    int center;

    if(left == right)
    {
        if(a[left])return a[left];
        else return 0;
    }


    center = (left + right) / 2;
    MaxLeftSum = Sum3Tem(a,left,center);
    MaxRightSum = Sum3Tem(a,center + 1,right);

    LeftBorder = 0;MaxLeftBorderSum = 0;
    for(int i = center; i >= left; i--)
    {
        LeftBorder += a[i];
        if(LeftBorder > MaxLeftBorderSum)MaxLeftBorderSum = LeftBorder;
    }

    rightBorder = 0;MaxRightBorderSum = 0;
    for(int i = center + 1;i <= right;i++)
    {
        rightBorder += a[i];
        if(rightBorder > MaxRightBorderSum)MaxRightBorderSum = rightBorder;
    }

    return max(max(MaxLeftSum,MaxRightSum),MaxRightBorderSum + MaxLeftBorderSum);

}

int Sum3(const int a[],int n)
{
    return Sum3Tem(a,0,n-1);
}


第四种

动态规划

状态转移方程

dp[i] = max(dp[i-1] + a[i],a[i]);

可以看这篇文章

int Sum4(const int a[],int n)
{
    int MaxSum = a[0];
    int SumTem = 0;
    for(int i = 0;i < n;i++)
    {
        SumTem += a[i];
        if(SumTem > MaxSum)MaxSum = SumTem;
        else if(SumTem  < 0)SumTem  = 0;
    }
    return MaxSum;
}
=======================

完整代码 测试数据总共有3000个 还在大了 要等太久 3000个可以看出差别了

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <fstream>

using namespace std;

//  O(n 3)
int Sum1(const int a[],int n)
{
    int maxSum = a[0];
    for(int i = 0;i < n ;i++)
        for(int j = i;j < n;j++)
        {
                int temSum = 0;
                for(int k = i;k <= j;k++)
                    temSum += a[k];
                if(temSum > maxSum)maxSum = temSum;
        }
        return maxSum;
}
//O (n 2)
int Sum2(const int a[], int n)
{
    int maxSum = a[0];
    for(int i = 0;i < n;i++)
    {
        int tem = 0;
        for(int j = i;j < n;j++)
        {
            tem += a[j];
            if(tem > maxSum)maxSum = tem;
        }
    }
    return maxSum;
}

int Sum3Tem(const int a[],int left,int right)
{
    int MaxLeftSum,MaxRightSum;
    int MaxLeftBorderSum,MaxRightBorderSum;
    int LeftBorder,rightBorder;
    int center;

    if(left == right)
    {
        if(a[left])return a[left];
        else return 0;
    }


    center = (left + right) / 2;
    MaxLeftSum = Sum3Tem(a,left,center);
    MaxRightSum = Sum3Tem(a,center + 1,right);

    LeftBorder = 0;MaxLeftBorderSum = 0;
    for(int i = center; i >= left; i--)
    {
        LeftBorder += a[i];
        if(LeftBorder > MaxLeftBorderSum)MaxLeftBorderSum = LeftBorder;
    }

    rightBorder = 0;MaxRightBorderSum = 0;
    for(int i = center + 1;i <= right;i++)
    {
        rightBorder += a[i];
        if(rightBorder > MaxRightBorderSum)MaxRightBorderSum = rightBorder;
    }

    return max(max(MaxLeftSum,MaxRightSum),MaxRightBorderSum + MaxLeftBorderSum);

}

int Sum3(const int a[],int n)
{
    return Sum3Tem(a,0,n-1);
}



int Sum4(const int a[],int n)
{
    int MaxSum = a[0];
    int SumTem = 0;
    for(int i = 0;i < n;i++)
    {
        SumTem += a[i];
        if(SumTem > MaxSum)MaxSum = SumTem;
        else if(SumTem  < 0)SumTem  = 0;
    }
    return MaxSum;
}


int main()
{

    const int num = 3000;
    //int a[6] = {-2,11,-4,13,-5,-2};
    int b[num];
    clock_t start,finish;



    freopen("randNum.txt","r",stdin);
    for(int i = 0;i < num;i++)
        cin>>b[i];

    start = clock();
    cout<<"sum1: "<<Sum1(b,num);
    finish = clock();
    cout<<" cost "<<double(finish - start) / CLOCKS_PER_SEC<<endl;

    start = clock();
    cout<<"sum2: "<<Sum2(b,num);
    finish = clock();
    cout<<" cost "<<double(finish - start) / CLOCKS_PER_SEC<<endl;

    start = clock();
    cout<<"sum3: "<<Sum3(b,num);
    finish = clock();
    cout<<" cost "<<double(finish - start) / CLOCKS_PER_SEC<<endl;

    start = clock();
    cout<<"sum4: "<<Sum4(b,num);
    finish = clock();
    cout<<" cost "<<double(finish - start) / CLOCKS_PER_SEC<<endl;


    return 0;
}







=====================================

为了得到测试数据

先写了一个随机数生成的程序,随机生成1000个数,范围[-100,100)

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cstdio>

using namespace std;

int main()
{

    srand(time(NULL));

    freopen("randNum.txt","w",stdout);
    int totalNum = 1000;
    while(totalNum--)
    {
        cout<<(rand() % 200  - 100)<<" ";
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值