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