编程珠玑读后感1(1个算法)

原创 2007年09月22日 17:56:00
 

HTML Tags and JavaScript tutorial



编程珠玑读后感1(1个算法)





在《编程珠玑》第八章,作者提出一道算法题:
程序描述:
输入是一个具有N个浮点数字的向量X: 其输出是在输入的任何相邻子向量中找出的最大和。
例如,输入如下10个元素:
31 -41 59 26 -53 58 97 -93 -23 84
返回 x[2..6]的总和,或为187
作者分别给出了三次算法O(n^3),两个二次算法O(n^2),分治算法O(n logn )和扫描算法O(n)。
我对该问题作了研究后,给出自己的一种解法。
考虑数组 x[ N ],我们新开辟一个数组sumX[ N + 1 ],其中sumX[ 0 ] = 0, 而 sumX[ i ] 为 x[ 0..i-1 ] 的和。
这样,对于 x[ i..j ]的和,有 sum( x[ i..j ] ) = sumX[ j+1 ] - sumX[ i ].
对于数组sumX, 假设最大值为 sumX[ posMax ], 最小值为 sumX[ posMin ],下面分三种情况:
1. posMin < posMax,也即最小值在最大值左边,我们可以肯定 x[ posMin..posMax-1 ] 就是所要求的总和。
否则,若x[ i..j ]是所要求的总和,且 i != posMin或 j != posMax,
则有sum( x[ i..j ] ) <= sum( x[ posMin, j ] ) <= sum( x[ posMin, posMax ] )
或sum( x[ i..j ] ) <= sum( x[ i, posMax ] ) <= sum( x[ posMin, posMax ] )
上面两不等式至少有一个严格小于,所以sum( x[ i..j ] ) < sum( x[ posMin, posMax ] )
由上可知,这种情况中返回结果 sumX[ posMax ] - sumX[ posMin ]
2. posMin == posMax,说明除了 x[ posMin ]外,其余x[ i ] 全为0
又由于sumX[ 0 ] = 0,所以 sumX[ posMax ] > 0
所以 x[ posMax - 1 ]是所要求的总和
这种情况中返回结果 sumX[ posMax ],也就是 x[ posMax-1 ] 一个元素
3.posMin > posMax
这种情况比较复杂,我们可以把sumX分为三部分:
a)sumX[ 0 ]..sumX[ posMax ];  b)sumX[ posMax + 1 ] ... sumX[ posMin - 1 ], c)sumX[ posMin ].. sumX[ N + 1 ].
我们可以肯定,要找出的x[ i..j-1 ],也可以认为是sumX[ i],sumX[j ]必在同一个小部分中。
否则,若 0 <= i <= posMax 而 posMax < j
则sum( x[ i..j-1 ] ) = sumX[ j ] - sumX[ i ] < sumX[ posMax ] - sumX[ i ]。
对于其他情况,也可以同样证明。
于是我们可以分别对数组a,b,c处理,找出最大和。
对数组a,找出最小值sumX[ posMin1 ],必有posMin1 < posMax,
于是结果 tmpMax1 = sumX[ posMax ] - sumX[ posMin1 ]
对数组c,找出最大值sumX[ posMax3 ],必有posMin < posMax3,
于是结果 tmpMax3 = sumX[ posMax3 ] - sumX[ posMin ]
对数组b,这是一个比开始问题规模更小的子问题,可再迭代处理,得到结果tmpMax2
这种情况中返回结果 tmpMax1, tmpMax2, tmpMax3中最大值
这种算法在最优情况下(posMin <= posMax)可看作一线性算法,运行时间O(n)
在最坏情况下(每次处理均有posMax = 0, posMin = 数组索引最大值,每个子问题规模减2),
这时可看作二次算法,运行时间O(n^2)
使用随机数调试,发现大部分情况运行时间在O( n logn ) 与 O( n^2 )之间。
测试结果:
N=10  N*logN=23  N*sqrtN=31  N^2=100  程序运行次数:27
N=100  N*logN=460  N*sqrtN=1000  N^2=10000  程序运行次数:404
N=1000  N*logN=6907  N*sqrtN=31622  N^2=1000000  程序运行次数:13009
N=10000  N*logN=92103  N*sqrtN=1000000  N^2=100000000  程序运行次数:683867 
 


编程珠玑——磁盘排序算法1

磁盘排序算法

《编程珠玑》阅读小记(1)— 开篇

1. 前言久闻《编程珠玑》一书的大名,一直没有找到合适的机会深入学习阅读,最近终于得以入手,便决心投入细细的研究,提升一下自己的编程思想与技术。阅读之后才发现,这本书确实一本不可多得的好书。它以计算机...
  • fly_yr
  • fly_yr
  • 2015年06月05日 15:26
  • 863

《编程珠玑(续)》学习笔记——第一章 性能监视工具(1)

一、例子:计算素数(prime number)     定义:质数,又称素数,指在大于1的自然数中,除了1和此整数自身外,无法被其他自然数整除的数(也可定义为只有1和本身两个因数的数)。(摘自维基百科...

编程珠玑之第三章习题1

问题描述: 1. 本书行将出版之时,美国的个人所得税分为5种不同的费率,其中最大的费率大约为40%。以前的情况更为复杂,税率也更高。下面所示的程序文本采用25个if语句的合理方式来计算1978年的美...

编程珠玑 Chap1

第一章中讨论的问题:给定最多1000万个无重复的7位整数,如何利用1MB(左右)的内存空间(磁盘空间充足)完成排序? 三种解决方案: 1.利用基于磁盘的归并排序。这种方法最容易想到,缺陷也很明显,归并...

《编程珠玑》读书笔记1----------------如何使用位逻辑来实现位向量

1.如何使用位逻辑来实现位向量 #define BITSPERWORD 32 //int型为32位 #define SHIFT 5 #define MASK 0x1F //模数 #d...

编程珠玑学习笔记1

编程珠玑学习笔记1 Posted on May 18, 2012 5 最近经历了腾讯和百度的实习生招聘,腾讯的十分顺利,拿到实习生offer,可能运气成分多一点,问我的问题我...

编程珠玑之第12章习题1: 随机位问题

习题描述:C库函数rand()通常返回约15个随机位。使用该函数实现函数bigrand和bigrand和randint(l, u), 要求前者至少返回30个随机位,后者返回[l,u]范围内的一个随机整...

整数二进制展开后1的个数(《编程珠玑》第九章)

转自博客:http://www.cnblogs.com/graphics/archive/2010/06/21/1752421.html

编程珠玑学习笔记(1):简单磁盘文件数据排序

问题描述: 输入:一个最多包含n个z
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:编程珠玑读后感1(1个算法)
举报原因:
原因补充:

(最多只允许输入30个字)