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

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

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

时间: 2024-08-02 11:04:05

第八章:再谈最大子数组问题的相关文章

[jQ/PHP]再谈使用JS数组储值的运用(提交PHP处理)

--------------------------------------------------------------------------------------------------- 从一个例子中看JS数组和对象的分工合作: /** * JS数组与对象使用.(传递多条json数据,实例局部) * @黑眼诗人 <www.chenwei.ws> */ function importL() { if(confirm('Sure?')) { var arr = []; var json

返回一个二维整数数组最大子数组的和

 要求: 1,输入一个二维整形数组,数组里有正数也有负数. 2,二维数组中连续的一个子矩阵组成一个子数组,每个子数组都有一个和, 3,求所有子数组的和的最大值. 设计思路: 参照一维整数数组求解最大子数组的方法,我们想着将二维数组通过行不同,列相加的方法转化为一维整数数组再求解最大子数组之和. 具体实现:先求出每一行的最大子数组之和,之后比较得出最大和MaxSum,然后通过上述方法求二行的最大子数组之和并与MaxSum比较,用MaxSum存放较大值.以此类推,求三行,四行... 最后实现最大子数

返回一个整数数组中最大子数组的和。(续2)---二维数组

求二维数组的最大子数组的和 思路:通过降维进行运算,每一行每次进行相同程度的加法运算,然后存到一个数组中就成了一维数组的求最大子数组的和,例如上图先进行[A][3]~[A][5]的求最大子数组的和,然后进行A列和B列相加再求最大子数组的和,如此循环到A+B+......+F,然后再从 B列开始进项如上操作,每一次求出最大子数组的和之后都会和最大值进行比较,然后选出最大值,输出结果.时间复杂度为O(n^4).....想不出来降低时间复杂度的方法... 代码如下 import java.util.S

软件工程课程作业(四)--返回一个整数数组中最大子数组的和

伙伴链接:http://www.cnblogs.com/haoying1994/ 一.设计思想 本实验要求输入一个正负数混合的整型数组,长度不限,在此数组的所有子数组中找到和最大的数组,并求出相应数组的和,且时间复杂度为O(n).我们在课堂上共同讨论了多种解决方案,这些将在下面可能的解决方案中展示,在听了同学的思路和老师的讲解之后, 我们最终选取了老师课堂上描述的比较简便的思路.如下: 在输入数组的环节,采用for无限循环加if判断截止,直到触发回车键为止,将数组记录到Array中,数组长度记录

分治策略 &nbsp; 最大子数组问题

递归式 递归式与分治方法是紧密相关的,因为使用递归式可以很自然地刻画分治算法的运行时间.一个递归式就是一个等式或不等式,它通过更小的输入上的函数值来描述一个函数.例如,在2.3.2节,我们用递归式描述了MERGE-SORT过程的最坏情况运行时间T(n): Θ(1)        若n=1 T(n) =                         (4.1) 2T(n/2)+Θ(n)    若n>1 求解可得T(n)=Θ(nlgn) 递归式可以有很多形式.例如,一个递归算法可能将问题划分为规模

最大子数组问题

小渣今天再来更新一波,欢迎看众 老爷们尽情喷(批评指导) 何为最大子数组:简言之,就是一数组A[n]中从i到j的连续子序列(i,j均在(0,n)区间内),且不存在另一对(a,b)对使得A[a]+A[a+1]+.....A[b]>A[i]+A[i+1]+...+A[j] 可见:①只有在数组含有负数元素时这个问题才有探讨的价值,否则整个数组本身即是最大子数组了: ②并且,i<=j(最大子数组可能只含有一个元素) ③最大子数组可能不唯一 思路:按照二分法来做,最大子数组两端无非有三种情况: 在左半部

结对开发——返回整数数组最大子数组和2

返回整数数组最大子数组和2 为了实现“敏捷开发”的目的,老师让我们采取“迭代”的方法进行项目的开发,这不,对于周一的求最大子数组和又有了新的要求,如下: 1.延续上次的要求,这里不再赘余… 2.如果数组A[0]……A[j-1]首尾相连,允许A[i-1],……A[n-1],A[0]……A[j-1]之和最大: 3.同时返回最大子数组的位置: 4.要求程序必须能处理1000 个元素,且每个元素是int32 类型的. 一.实验设计思路 首先实现的是数组首尾相连,先存入数组,再将原数组反向存储形成环形数组

课后实验4--返回一个整数数组中最大子数组的和

伙伴链接:http://www.cnblogs.com/chengqiqin07/ 一.设计思想 本实验要求输入一个正负数混合的整型数组,长度不限,在此数组的所有子数组中找到和最大的数组,并求出相应数组的和,且时间复杂度为O(n).我们在课堂上共同讨论了多种解决方案,这些将在下面可能的解决方案中展示,在听了同学的思路和老师的讲解之后, 我们最终选取了老师课堂上描述的比较简便的思路.如下: 在输入数组的环节,采用for无限循环加if判断截止,直到触发回车键为止,将数组记录到Array中,数组长度记

返回一个整数数组中最大子数组的和4

题目:返回一个二维整数数组中最大子数组的和. 要求: 1 输入一个二维整形数组,数组里有正数也有负数. 2 二维数组首尾相接,象个一条首尾相接带子一样. 3 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 4 求所有子数组的和的最大值.要求时间复杂度为O(n). 设计思想 目前的解决方案是最笨的方法,穷举,所以时间复杂度达不到题目的要求,还需要进一步的寻找答案 源代码 题目:返回一个二维整数数组中最大子数组的和. 要求: 1 输入一个二维整形数组,数组里有正数也有负数. 2 二