如何提高程序的效率(一)

                  ――设计优秀的算法

(From Programming Peals by Jon Bentley)

一个简单的问题,往往有许多不同的解决方案,那么如何找到一个相比之下比较好(事实上很难找到绝对好的方法)的方案呢?我们需要一个优秀的算法,优秀的算法能够给很大程度上提高程序的效率。

问题描述:问题的输入是具有n个整数的向量x,输出是输入向量的任何连续子向量中的最大和。例如,如果输入向量包含下面10个元素:
31
41 59 26 53 58  979323  84

当所有的输入都是正数的时候,问题很容易解决,此时最大的子向量就是整个输入向量。

但是,如果出现负数该怎么办,这就是我们下面所研究的几个算法所讨论的内容。

 

一个简单平方算法(On2)):

int maxsofar=0;

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

{

  sum=0 ;

  for(int j=I;j<n;j++)

{

  sum+=x[j];

  maxsofar= max( maxsofar,sum );

}

}

 

 

一个分治算法(O(log n)):

分治原理:

     要解决规模为n的问题,可递归地解决两个规模近似为n/2的子问题,然后对他们的答案进行合并以得到整个问题的答案。

程序略

 

 

一个现在看来最高效的程序——scan算法(O(n):

下面给出此程序的C++完整代码:

#include <iostream.h>

//#include <stdlib.h>

int max(int a,int b)

{

      return a>b?a:b;

}

int scan(int a[],int n)

{

      int maxsofar,maxendinghere;

      maxsofar=maxendinghere=0;

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

      {

      maxendinghere=max(maxendinghere+a[i],0);

         maxsofar=max(maxsofar,maxendinghere);

      }

      return maxsofar;

}

 

void main()

{

      int a[10]={-6,-8,-89,7,3,8,-79,45,8,-5};

      cout<<scan(a,10)<<endl;

 

}

 

可以看出scan算法是一个接近完美的算法,因为解决这个问题少于O(n)是不可能的。



附上结构之法算法之道blog的解法:

#include <iostream>
using namespace std;


//结构之法算法之道blog的算法
/*-------------------------------------
解释下:
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,
那么最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。


所有的东西都在以下俩行,
即:
b  :  0  1  -1  3  13   9  16  18  13
sum:  0  1   1  3  13  13  16  18  18


其实算法很简单,当前面的几个数,加起来后,b<0后,
把b重新赋值,置为下一个元素,b=a[i]。
当b>sum,则更新sum=b;
若b<sum,则sum保持原值,不更新。。July、10/31。


此法和编程珠玑中方法本质是一样的
----------------------------------*/
int maxSum(int* a, int n)
{
    int sum=0;
    //其实要处理全是负数的情况,很简单,如稍后下面第3点所见,直接把这句改成:"int sum=a[0]"即可
    //也可以不改,当全是负数的情况,直接返回0,也不见得不行。
    int b=0;


    for(int i=0; i<n; i++)
    {
        if(b<0)           //...
            b=a[i];
        else
            b+=a[i];
        if(sum<b)
            sum=b;
    }
    return sum;
}
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值