代码改变世界

一维向量中查找任何相邻子向量的最大和

2010-08-02 22:02  Aga.J  阅读(1598)  评论(5编辑  收藏  举报

  今天看到《编程珠玑》的第八章,里面提出了这个问题:

  文章给了四种不同级别的算法,从n的三次方的时间开销到n的时间开销,在给出第2种算法(只需要n的平方,并且我第一次做的话也是这种做法)后,文章问读者能不能给出更快速的方法,于是我放下了书,自己想了想:

  一开始想到的是一个递归的算法,每次遇到负数时都跳过,直到再次遇到正数,这时候已经形成了递归子式,然后递归返回是什么呢?就是拿递归子式和进行该递归前的所有负数之和进行比较,如果它们之和大于零则继续递归返回,如果小于零则抛弃。

  但是这个算法实现起来比较麻烦,要记录的现场比较多,然后就继续想了想,突然想到,要是向量总是从负数开始,那么前面的负数在一开始就不用考虑,所有就有了抛弃前置负数和抛弃后置负数的想法(抛弃后置负数其实也就是抛弃前置负数,只要把向量顺序逆一下就是同个道理了),但是发现这样的话又得用递归,因为虽然抛弃了前后的负数,但是中间还再需要进行这样的抛弃。

  最后,在抛弃前置和后置负数的基础上,我得到了下面这样的解法

 int max=0;
 int temp=0;
 for(int k=9;k>=0;k--)
 {
  temp=i[k]+temp;
  
  if(temp<0)temp=0;
  else max=getMax(max,temp);
 }
 cout<<max;
这里利用的是后置负数的好处,将后置的负数从后往前抛弃,然后记得记录下当前最大数,因为在前面可能会加上一个负数而没被纳入抛弃的范围。这种方法的时间复杂度和书里面介绍的最后一种方法是一样的,都是n的大O,而书里给出的算法名词是扫描算法,也有这种意思在里面吧。

  最后,我该休息了,我想既然能用到后置负数的好处,那么前置负数的好处也能用上,因为“后置”就是“前置”嘛,不过还需要考虑前后这样的扫描的终止情况,怎么又觉得有点双向冒泡的感觉了。。。