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


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

    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之间的行驶费用。

  • 相关阅读:
    Java 处理 iphone拍照后 图片EXIF属性翻转90度的方法
    spring boot文件上传、下载
    python dict.get()和dict['key']的区别
    python zip()
    Pythonn new-style class and old-style class
    mysql错误
    django 模板中url的处理
    python中isort的使用
    使用uWSGI部署django项目
    django处理静态文件
  • 原文地址:https://www.cnblogs.com/bukekangli/p/4329716.html
Copyright © 2020-2023  润新知