码迷,mamicode.com
首页 > 编程语言 > 详细

第八章:再谈最大子数组问题

时间:2015-03-11 21:13:58      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:

前段时间看《算法导论》了解到最大子数组问题,但没有做习题,遗漏了一些重要的知识,现在《编程珠玑》上看到完整的讲解,还有一些算法技巧,故记录于此。

1.定义问题

在数组中找出元素之和最大的子数组,假定当数组元素全部为负数时,最大子数组是空数组,和为0。

 

2.解决问题

令数组为x[n],最大子数组下标为[p,q]。

2.1算法1:时间复杂度O(n3)

maxsofar=0
for i=[0,n)
    for j=[0,n)
        sum=0
        for k=[i,j]
            sum+=x[k]
        if(sum>maxsofar)
            maxsofar=sum
            [p,q]=[i,j]

2.2算法2:时间复杂度O(n2)

注意到x[i..j]的总和与x[i..j-1]密切相关,可以用“缓存”的思维改进算法1。得到算法2a

算法2a:

maxsofar=0
for i=[0,n)
    sum=0
    for j=[i,n)
        sum+=x[j]   
        if(sum>maxsofar)
            maxsofar=sum
            [p,q]=[i,j]    

“将信息预处理到数据结构中”“累积”的思维,得到2b

算法2b:

cumarr[-1]=0
for i=[0,n)
    cumarr=cumarr[i-1]+x[i]//cumarr的第i个元素保存了x[0..i]的和
maxsofar=0
for i=[0,n)
    for j=[i,n)
        sum=cumarr[j]-cumarr[i-1]
        if(sum>maxsofar)
            maxsofar=sum
            [p,q]=[i,j] 

2.3算法3:时间复杂度O(n lgn)

算法3采用分治策略,见这篇博客

2.4算法4:时间复杂度O(n)

算法4是扫描算法,有关数组的问题经常可以通过询问“我如何将x[0..i-1]的解决方案拓展到x[0..i]的解决方案?”的方式来解决。

maxsofar=0
maxendinghere=0
for i=[0,n)
    maxendinghere=max(maxendinghere+x[i],0)//如果0较大,p=i
    maxsofar=max(maxsofar,maxendinghere)//如果maxedninghere较大,q=i

 

3.此算法进化过程中说明的几个重要的算法设计技术

技术分享

 

4.习题解答

9.该问题对最大子数组的定义就是《算法导论》最大子数组的初始定义,故算法3变为这样。其它算法将maxsofar的初始值设为-∞即可。

10.初始化累加数组cum,使cum[i]=x[0]+...+x[i],如果cum[i]==cum[j],那么x[i..j-1]的和为0。具体实现可以将cum数组排序,然后在对于每个cum[i]调用二分查找,可在O(n lgn)时间内完成任务。为了得到i,j的值,在排序时需要记住每个元素原来的下标。

11.利用上述累加数组cum的思路,cum[i]记录收费站0到i之间的行驶费用。

 

第八章:再谈最大子数组问题

标签:

原文地址:http://www.cnblogs.com/bukekangli/p/4329716.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!