书中的算法。


358

保罗·埃尔多斯(Paul Erdos)谈论了“书”,其中上帝保留了每个数学定理的最优雅的证明。这甚至启发了一本书(我相信现在是第四版):书中的证明

如果上帝有一本类似的算法书,那么您认为哪种算法是候选人?

如果可能的话,还请提供可点击的参考以及使之起作用的关键见解。

请每个答案仅使用一种算法。


11
好问题![编辑:}一个问题。我们在哪里划定算法和数据结构之间的界限?如果对算法的关键了解与数据结构密切相关(例如,逆阿克曼函数中的UNION FIND),该怎么办?
罗斯·斯尼德


21
我觉得有些棘手的算法(KMP,线性后缀数组)被其他人认为是“出自本书”,这让我有些惊讶。对我而言,“从书中”的意思是简单明了,但只是事后回想。我很好奇别人如何解释“优雅”。
Radu GRIGore 2010年

49
@supercooldave您不必相信上帝,但您应该相信他的书。;-)
Ross Snider 2010年

10
在1985年的一次演讲中,埃尔德斯说:“您不必相信上帝,但您应该相信《圣经》。”
罗伯特·马塞利

Answers:


116

联合查找是一个美丽的问题,其最佳算法/数据结构(不相交集森林)是基于意大利面条堆栈的。尽管非常简单直观,足以向聪明的孩子讲解,但花了好几年时间才能确定其运行时间。最终,它的行为被发现与逆阿克曼函数有关,该函数的发现标志着关于计算的观点发生了转变(实际上已包含在希尔伯特的《无限》中)。

Wikipedia很好地介绍了Disjoint Set Forests


109

Knuth-Morris-Pratt字符串匹配。您将看到的最漂亮的八行代码。


4
我有点不知所措地意识到,这在某些时候并不明显,现在才变得明显,因为他们提出来了,并且我们学会了……我认为我们应该将卡尔的历史理论应用到数学和计算机科学中。
Ritwik Bose

1
通过描述,我想说这与Boyer-Moore快速子字符串搜索有关。
巴特2010年

2
@Mechko该算法是由独立的人同时独立发现的,这表明它在一定程度上是显而易见的。项目是否“明显”取决于项目约束和更广泛的编程环境。如果您需要(1)快速文本搜索,并且(2)了解真正的O(n)算法的重要性,并且(3)您之前遇到过部分匹配的文本,并且(4)您有时间做“正确”的事情,那么这种算法可能很明显。
Matt Gallagher 2013年

克努斯(Knuth)在接受采访时说,该算法的思想来自研究斯蒂芬·库克(Stephen Cook)的回文双向有限自动机
卡夫(Kaveh)2014年

@Kaveh请阅读原始KMP论文的第7节(历史记录)。它有很好的评论。关于莫里斯(Morris)编写的文本编辑器,“对于系统的其他实现者来说太复杂了,难以理解”。关于Knuth“在Knuth的经验中,第一次有自动机理论教会他如何比以前更能解决实际的编程问题”。并且“ Knuth苦于得知莫里斯已经在不知道库克定理的情况下发现了该算法;”。好玩
Hendrik 2014年1

93

百隆,弗洛伊德,普拉特,维斯特和的Tarjan的算法找到ķ个未排序列表的元素以线性时间是一个美丽的算法,只有工作,因为数字是恰到好处,以适应在主定理。内容如下:

  1. 对五个元素的每个序列进行排序。
  2. 挑选每个中位数。
  3. 再次查找该列表的中位数。
  4. 在中位数上枢转(如Quicksort中所示)
  5. 选择列表的适当位置并在列表中定位,然后重复进行。

3
这是我最喜欢的算法之一。我喜欢从Chazelle的差异书中学到的一种直觉:元素组的中位数集就像 -net一样,用于输入数字的有序列表中的间隔。因此,该算法遵循一个通用范例:快速计算 -net,在网络上解决问题,递归输入的一部分以精炼解决方案,直到获得确切的解决方案为止。这是非常有用的技术ε ε1/ϵϵϵ
Sasho Nikolov 2012年

5
顺便说一句,一旦参数化了组的大小,常量就不再那么神奇了。它们当然经过了优化,可以在主定理中做出正确的选择
Sasho Nikolov 2012年

Ruby实现,gist.github.com/chadbrewbaker/7202412是否有使用(恒定,对数)空间的算法版本,还是必须使用线性暂存空间来保存中位数?
乍得·布鲁贝克2013年

2
声称“这仅是因为数字恰好适合主定理而起作用”的说法并不是真的。如果将数字替换为较大的,则很容易看出,两个总和小于数字将收敛为和,因此所有足够大的起作用。只是第一个起作用的数字,不是唯一的一个。Ñ 1 3 / 4 0 Ñ 55n13/40n5
萨温(Wal Sawin)2015年

88

二进制搜索是我遇到过的最简单,最漂亮,最有用的算法。


我会用直观代替优雅。没有什么比它优雅的了。它的简单是其真正的美。
罗伯特·马塞利

@Robert Massaili:我用美丽代替了优雅。你是对的。
michalmocny

2
而且疯狂地难以正确编写-请参阅“ 您是可以编写二进制搜索的10%的程序员之一吗?
jon 2013年

在我的第一门研究生算法课程中,我们进行了15分钟的测验,其中我们需要手工解决2-3个问题。第一个这样的测验包括一个二叉搜索树和两个关于堆的问题。在得知有人在大约30个人的班级中有两个正确答案之前,我感到很尴尬和沮丧,因为我发现自己错误地发现了二进制搜索问题。但是,即使知道这一点,专业团体才花了15年的时间才能做到这一点令人震惊。
Stella Biderman

84

我很惊讶没有在这里看到所有对的最短路径的Floyd-Warshall算法

d[]: 2D array. d[i,j] is the cost of edge ij, or inf if there is no such edge.

for k from 1 to n:
  for i from 1 to n:
    for j from 1 to n:
      d[i,j] = min(d[i,j], d[i,k] + d[k,j])

考虑到可能存在边时,最短,最清晰的非平凡算法之一和性能非常敏捷。那将是我进行动态编程的招贤纳士!O n 2O(n3)O(n2)


2
该算法也可以以一种非常整洁的方式推广。参见例如r6.ca/blog/20110808T035622Z.htmlcl.cam.ac.uk/~sd601/papers/semirings.pdf
Mikhail


73

可能看起来有些琐碎(尤其是与其他答案相比),但是我认为Quicksort确实很优雅。我记得当我第一次看到它时,我认为它确实很复杂,但是现在看来太简单了。


10
Quicksort还提出了有关算法本质到底是什么的有趣问题。例如,标准的优雅Haskell实现看上去与标准的伪代码定义完全相同,但是它具有不同的渐近复杂度。因此,Quicksort仅仅是分治,还是聪明的原地指针摆放是Quicksort的重要组成部分?Quicksort甚至可以在纯功能设置中实现吗,或者它需要可变性吗?
约尔格W¯¯米塔格

2
算法的“本质”或“道德”思想当然来自美丽的论文,作者是Melissa E. O'Neill 撰写的《 Eratosthenes的真正筛子》cs.hmc.edu/~oneill/papers/Sieve-JFP。 pdf)和快速排序讨论来自该文件的LtU讨论(lambda-the-ultimate.org/node/3127),特别是从以下评论开始:lambda-the-ultimate.org/node/3127/#comment-45549
约尔格W¯¯米塔格

8
@Jörg:在链表上实现quicksort是完全明智的,并且与在数组上就地实现具有相同的渐近运行时间(哎呀,即使是在数组上的天真过时实现也具有相同的运行时间)–都在平均,最坏的情况。关于空间使用,这确实是不同的,但是必须说,即使是“就地”版本也需要非恒定的额外空间(调用堆栈!),这一事实很容易被忽略。
康拉德·鲁道夫

同样值得一提的是弗拉基米尔·雅罗斯拉夫斯基(Vladimir Yaroslavskiy)的Dual-Pivot Quicksort。那应该比原始
quicksort

快速排序理论上很简单(可以分4个步骤概述),并且可以高度优化,但实际上很难正确编码。这就是为什么它没有得到我的投票。
丹尼斯


50

米勒-拉宾检验(以及类似的测试)应该是在这本书中。这个想法是利用质数的性质(即使用费马小定理)来概率性地寻找数字不是质数的证人。如果在经过足够的随机测试后未找到证人,则该数字为素数。

值得注意的是,显示PRIMES在P中的AKS素数测试当然应该在The Book中!


49

Schwartz-Zippel引理进行多项式恒等式检验:

如果某人在半夜把您叫醒,并要求您测试两个单变量多项式表达式的身份,您可能会将它们简化为乘积和的形式,并比较结构身份。不幸的是,减少可能要花费指数时间。这类似于将布尔表达式简化为析取范式。

假设您是喜欢随机算法的那种,那么您的下一个尝试可能是在随机选择的点上评估多项式以查找反例,并声明多项式如果通过了足够的测试就很可能是相同的。Schwartz-Zippel引理表明,随着分数数量的增加,假阳性的机会会迅速减少。

没有确定的算法可以在多项式时间内运行。


这应该早就建议了!谢谢!
arnab

1
书中还有其他一些随机算法值得关注。对于这些,确定性和概率性选择之间的对比不太明显:确定性算法通常存在,但要复杂得多。
Per Vognsen 2010年

几年前,当我在论文上工作时,我独立地发明了相同的算法,直到有人问我这不是施瓦茨-齐佩尔引理吗?我说,那是什么?:)
Helium 2015年

46

深度优先搜索。它是许多其他算法的基础。这也是欺骗性简单:例如,如果你通过一个栈替换在BFS执行队列中,你得到DFS?


1
这也是执行Prolog的基础!
muad 2010年

1
我缺少的具有堆栈的BFS有什么意义?我以为答案是“是的,您得到了DFS”。
OmarAntolín-Camarena13年

1
好吧,每个人似乎都认为这个问题微不足道。另外,每个人似乎都认为答案是“是”,这是错误的。答案实际上是“取决于您从哪个BFS实现开始”。请参阅cs.stackexchange.com/questions/329/…(这是我发布的有关帮助CS.SE Beta版的问题)
Radu GRIGore 2013年


42

Dijkstra的算法:具有非负边路径成本的图的单源最短路径问题。它无处不在,是那里最漂亮的算法之一。没有它,就无法路由互联网-它是路由协议IS-IS和OSPF(开放式最短路径优先)的核心部分。

  1. 为每个节点分配一个距离值。对于我们的初始节点,将其设置为零;对于所有其他节点,将其设置为无穷大。
  2. 将所有节点标记为未访问。将初始节点设置为当前节点。
  3. 对于当前节点,请考虑其所有未访问的邻居,并计算它们的暂定距离(距初始节点)。例如,如果当前节点(A)的距离为6,并且将其与另一个节点(B)相连的边为2,则通过A到B的距离将为6 + 2 = 8。如果该距离小于先前记录的距离(开始时为无穷大,初始节点为零),则覆盖该距离。
  4. 考虑完当前节点的所有邻居后,将其标记为已访问。访问过的节点将不再被检查;现在记录的距离是最终的并且是最小的。
  5. 如果已访问所有节点,请完成。否则,将(到初始节点)距离最小的未访问节点设置为下一个“当前节点”,然后从步骤3继续。


40

Gentry的完全同态加密方案(在理想晶格上或在整数上)非常漂亮。它允许第三方在不访问私钥的情况下对加密数据执行任意计算。

加密方案是基于几个敏锐的观察结果。

  • 为了获得完全同态的加密方案,只需要一种在加法和乘法上是同态的方案即可。这是因为加法和乘法(模2)足以获得AND,OR和NOT门(因此具有Turing完整性)。
  • 如果必须有这样一种方案,但是由于某些限制只能对有限深度的电路执行,则可以同态评估解密和重新插入过程以重置电路深度限制,而不会牺牲密钥私密性。
  • 通过“压缩”该方案的解密函数的电路版本的深度,可以使一种最初限于有限,浅层电路的方案能够进行任意数量的计算。

在他的论文中,克雷格·金特里(Craig Gentry)解决了密码学中一个长期存在(且华丽)的开放问题。确实存在完全同态方案的事实要求我们认识到,可计算性存在一些固有的结构,否则我们可能会忽略它们。

http://crypto.stanford.edu/craig/craig-thesis.pdf

http://eprint.iacr.org/2009/616.pdf

http://portal.acm.org/citation.cfm?id=1666420.1666445





34

构造后缀数组的线性时间算法确实很漂亮,尽管它并没有得到应有的认可http://www.cs.helsinki.fi/u/tpkarkka/publications/icalp03.pdf


确实认为它已经得到了应有的认可-您为何不这样认为?例如,它在C ++序列分析库SeqAn中实现。
康拉德·鲁道夫

值得一提的是,现在还有许多其他的线性和非线性时间后缀数组构造算法,尽管它们相差甚远,但在实践中可能要快得多。实验算法学报(JEA),第12卷,2008年6月,“一种有效的,通用的后缀排序方法”,沿着这些思路有一些实验结果。
拉斐尔

@Raphael:我有点警惕p上的事实。该JEA纸3,他们只给了他们“相信”是一个“松散”约束为O(n ^ 2 log n)的的...你知道有任何文件可证明的线性时间的算法更快实际上比偏斜算法?
2011年

32

高斯消除。它完成了从欧几里得GCD算法到Knuth-Bendix的泛化序列。


顺便说一句,什么是泛化序列,Buchberger基于Grobner的算法在哪里适合?(这似乎与Knuth-Bendix类似,但我在某个地方提到过某种提法,它概括了高斯
消隐法

6
顺序为:欧几里得GCD->高斯消除-> Buchberger-> Knuth-Bendix。也可以放入(而不是高斯消除)单变量多项式除法和模(按广义顺序,它除高斯消除外,GE为多元度1,多项式环为单变量无限度,Buchberger为多元无限度。由于变量的增加,泛化跃迁从EGCD到GE或多项式环最大,而从Buchberger到KB则由于无限签名而大。–
Mitch

+1:欧几里得算法可解决数学上最著名的方程ax-by = 1。为什么它不经常出现在CS中是一个谜。
Tegiri Nenashi 2011年

32

当我第一次看到油藏采样算法及其证明时,给我留下了深刻的印象。它是典型的“脑筋急转弯”式拼图,具有非常简单的解决方案。我认为它绝对属于本书,既涉及算法又涉及数学定理。

至于这本书,故事是这样的:当埃尔多斯死后去天堂,他要求与上帝见面。该请求被批准,而Erdös在会议上只有一个问题。“我可以看书吗?” 上帝说是,并带领Erdös去了。自然而然的激动,Erdös打开书仅看到以下内容。

定理1:...
证明:显而易见。

定理2:……
证明:显而易见。

定理3:...
证明:显而易见。


4
定理4:……证明:对读者进行练习。
2013年

31

乌龟和野兔算法。我喜欢它,因为我确信即使我一生都在浪费时间去寻找它,我也绝不会想出这样的主意。


6
您是否知道用相同的渐近线解决问题并遵循算法设计模式的笨拙算法?我说的是迭代加深。在第n次迭代中,您从根的第2 ^ n个后继者开始,向前寻找2 ^ n个后继者以寻找重复。即使您每次迭代都在回溯某些步骤,搜索半径的几何增长率也意味着它不会影响渐近线。
Per Vognsen 2010年

30

欧几里得证明无穷多个素数的一个基本且“琐碎”的例子:

MAX-CUT的2逼近 -对每个顶点独立地,以相等的概率将其分配给两个分区之一。


6
是的,一个非常好的算法。不那么琐碎,以另一个2的代价为代价,该算法也可用于最大化任何子模函数,而不仅仅是图割函数。这是来自FOCS 07的Feige,Mirrokni和Vondrak的结果
Aaron Roth 2010年

30

我一直都喜欢Christofides的算法,该算法为公制TSP提供(3/2)近似值。实际上,称呼我为好,但我什至喜欢它之前的2-近似算法。Christofides通过添加奇数度顶点的匹配项(而不是复制所有边缘)来使最小权重的生成树Eulerian的技巧简单而优雅,并且几乎没有理由说服这种匹配的权重不超过一半最佳游览。


确实,还有许多其他的简单且优雅的近似算法,都具有不错的近似保证。
Janne H. Korhonen 2010年



25

线性编程的算法:单纯形,椭圆形和内点法。

http://en.wikipedia.org/wiki/Linear_programming#Algorithms


的确,由于提高了我们对这些问题的理解,他们获得了多个诺贝尔奖。
罗斯·斯尼德

@Ross Kantorovich发明了LP并将其应用于资源分配而获得了诺贝尔经济学奖。您还在想什么其他奖项?
Mark Reitblatt 2010年

@马克·库珀曼斯(Mark Koopermans)被坎托罗维奇(Kantorovich)授予诺贝尔奖,但我说“几个”仍然不准确。
罗斯·斯尼德

22

Robin Moser算法用于解决某类SAT实例。Lovasz Local Lemma可以解决此类情况。Moser算法的确是对引理陈述的去随机化。

我认为他的算法(以及证明其正确性的技术)将在几年后被很好地消化和精炼,成为本书中可行的算法候选人。

此版本是他与GáborTardos撰写的原始论文的扩展。




20

我认为我们必须包括Schieber-Vishkin,它可以在恒定时间内回答最低的共同祖先查询,并在线性时间内对森林进行预处理。

我喜欢Knuth在第4卷Fascicle 1中的论述以及他的沉思。他说他花了整整两天的时间才能完全理解它,我记得他的话:

我认为它很漂亮,但令人惊讶的是,它在文学作品中受到了很大的反响(..)它是基于使我兴奋的数学方法。


10
等等,它也许很漂亮,但是如果Knuth花了整整两天的时间来完全理解它,那真的是“从书上”吗?
ShreevatsaR

@ShreevatsaR这本书的脚注中有精美的印刷品:)
hsmyers 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.