最大子列和(算法复杂度优化)

#include <stdio.h>
#include <math.h>
#include <time.h>
#define MAXK 1e7

clock_t start,stop;
double duration;

/*一种复杂度为O(n^3)的暴力解法*/ 
int MaxSubseqSum1(int A[],int N) 
{
   int ThisSum,MaxSum=0;
   int i,j,k;
   for(i=0;i<N;i++){ //i是子列左端位置 
   for(j=i;j<N;j++){ //j是子列右端位置 
   ThisSum=0;        //ThisSum是从A[i]到A[j]的子列和 
   for(k=i;k<=j;k++)
    ThisSum +=A[k];
   if(ThisSum>MaxSum) //如果刚得到的这个子列和更大 
    MaxSum=ThisSum;   //则更新结果 
   } 
  }
  return MaxSum;
}



/*复杂度为O(n^2)的算法*/
int MaxSubseqSum2(int A[],int N)
{
    int ThisSum,MaxSum=0;
    int i,j;
    for(i=0;i<N;i++){
        ThisSum=0;  //ThisSum是从A[i]到A[j]的子列和
        for(j=i;j<N;j++){
            //对于相同的i,不同的j,只要在j-1次循环的基础上累加一项即可
            ThisSum +=A[j];
            if(ThisSum>MaxSum)
            MaxSum=ThisSum; 
        }
    }
    return MaxSum;
 } 


/*分而治之算法,复杂度为O(NlogN)*/ 

 int Max3( int A, int B, int C )
{   //返回3个整数中的最大值 
    return A > B ? A > C ? A : C : B > C ? B : C;
}

int DivideAndConquer( int List[], int left, int right )
{   //分治法求List[left]到List[right]的最大子列和 
    int MaxLeftSum, MaxRightSum; //存放左右子问题的解 
    int MaxLeftBorderSum, MaxRightBorderSum; //存放跨分界线的结果
    int LeftBorderSum, RightBorderSum;
    int center, i;

    if( left == right )  //递归的终止条件,子列只有1个数字 
        if( List[left] > 0 )  return List[left];
    else return 0;

    //下面是"分"的过程 
    center = ( left + right ) / 2; //找到中分点 
    //递归求得两边子列的最大和
    MaxLeftSum = DivideAndConquer( List, left, center );
    MaxRightSum = DivideAndConquer( List, center+1, right );

    //下面求跨分界线的最大子列和 
    MaxLeftBorderSum = 0; LeftBorderSum = 0;
    for( i = center; i >= left; i-- ) { // 从中线向左扫描
        LeftBorderSum += List[i];
        if( LeftBorderSum > MaxLeftBorderSum )
            MaxLeftBorderSum = LeftBorderSum;
    } // 左边扫描结束 
    MaxRightBorderSum = 0; RightBorderSum = 0;
    for( i = center + 1; i <= right; i++ ) { // 从中线向右扫描
        RightBorderSum += List[i];
        if( RightBorderSum > MaxRightBorderSum )
            MaxRightBorderSum = RightBorderSum;
    } //右边扫描结束 

    //下面返回"治"的结果 
    return Max3( MaxLeftSum, MaxRightSum,
                 MaxLeftBorderSum + MaxRightBorderSum );
}

int MaxSubseqSum3( int List[], int N )
{   //保持与前2种算法相同的函数接口 
    return  DivideAndConquer( List, 0, N-1 );
}


/*在线处理算法,复杂度为O(N),每输入一个数据就进行即时处理,在任何地方中止输入,算法都能正确给出当前的解*/ 
int MaxSubseqSum4(int A[],int N)
{
    int ThisSum,MaxSum;
    ThisSum=MaxSum=0;
    for(int i=0;i<N;i++){
     ThisSum +=A[i];
     if(ThisSum>MaxSum)
      MaxSum=ThisSum;
     else if(ThisSum<0)
      ThisSum=0; 
    }
    return MaxSum;
 } 

 int main()
 {
    int i,N;
    scanf("%d",&N);
    int a[N];
    for(i=0;i<N;i++){
        scanf("%d",&a[i]);
     }
    start=clock();
    for(int i=0;i<MAXK;i++) //重复调用函数以获得充分多的时钟打点数 
     MaxSubseqSum1(a,N);
    stop=clock();
    duration=((double)(stop-start))/CLK_TCK/MAXK;
    printf("%d\n",MaxSubseqSum1(a,N));
    printf("ticks1=%f\n",(double)(stop-start));
    printf("duration1=%6.2e\n",duration); 


    start=clock();
    for(int i=0;i<MAXK;i++) //重复调用函数以获得充分多的时钟打点数 
     MaxSubseqSum2(a,N);
    stop=clock();
    duration=((double)(stop-start))/CLK_TCK/MAXK;
    printf("%d\n",MaxSubseqSum2(a,N));
    printf("ticks2=%f\n",(double)(stop-start));
    printf("duration2=%6.2e\n",duration); 

    start=clock();
    for(int i=0;i<MAXK;i++) //重复调用函数以获得充分多的时钟打点数 
     MaxSubseqSum3(a,N);
    stop=clock();
    duration=((double)(stop-start))/CLK_TCK/MAXK;
    printf("%d\n",MaxSubseqSum3(a,N));
    printf("ticks3=%f\n",(double)(stop-start));
    printf("duration3=%6.2e\n",duration); 

    start=clock();
    for(int i=0;i<MAXK;i++) //重复调用函数以获得充分多的时钟打点数 
     MaxSubseqSum4(a,N);
    stop=clock();
    duration=((double)(stop-start))/CLK_TCK/MAXK;
    printf("%d\n",MaxSubseqSum4(a,N));
    printf("ticks4=%f\n",(double)(stop-start));
    printf("duration4=%6.2e\n",duration); 


     return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值