更糟糕的是更好。有一个例子吗?

时间:2009-01-23 01:35:32

标签: algorithm time-complexity

是否存在一种广泛使用的算法,其时间复杂度更差比另一种已知算法更好选择 all 实际情况( 更糟 复杂但更好否则)?

可接受的答案可能是以下形式:

  

有算法AB   有O(N**2)O(N)时间   相应的复杂性,但B   它有一个很大的常数,它没有   输入少于A的优势   然后是一些原子   宇宙。

答案的例子突出显示:

  • 单纯形算法 - 最坏情况是指数时间 - vs。已知的多项式时间算法用于凸优化问题。

  • 中位数中位数算法 - 最坏情况O(N ** 2) vs 已知O(N)算法。

  • 回溯正则表达式引擎 - 最坏情况指数 vs。 O(N)基于Thompson NFA的引擎。

所有这些例子都利用了最坏情况和平均情况。

是否存在不依赖于最坏情况与平均情况之间差异的示例?


相关:

  • The Rise of ``Worse is Better''。 (出于这个问题的目的,“更糟糕的是更好”这个短语用于 narrower (即 - 算法时间复杂度)意义而不是文章中。

  • Python's Design Philosophy

      

    ABC集团努力追求完美。   例如,他们使用基于树的数据   经过验证的结构算法   对于渐近大的最优   收藏品(但不是很好   小收藏品。)

    如果没有能够存储这些大型集合的计算机(换句话说,大型集合在这种情况下不够大),这个例子就是答案。

  • 方阵矩阵乘法的
  • Coppersmith–Winograd algorithm是一个很好的例子(它是最快的(2008),但它不如更差的算法)。 其他人? 来自维基百科的文章:“它并没有在实践中使用,因为它只为矩阵提供了一个优势,使它们无法被现代硬件处理(Robinson 2005)。”

24 个答案:

答案 0 :(得分:34)

quick-sort的最坏情况时间复杂度为O(N ^ 2),但通常认为它比其他在最坏情况下具有O(N log n)时间复杂度的排序算法更好。

答案 1 :(得分:28)

Simplex是一种在最坏情况下具有指数时间复杂度的算法,但对于任何实际情况,它都是多项式。可能是线性规划的多项式算法exist,但它们非常复杂,通常有很大的常数。

答案 2 :(得分:15)

在语言中也可以看到“更糟糕更好”,例如Perl,Python,Ruby,Php甚至C#或Java背后的思想,或者不是汇编程序或C语言的任何语言(C ++可能适用于此处)

基本上总是有一个“完美”的解决方案,但很多时候使用“更糟糕的”工具/算法/语言来更快地获得结果并且痛苦更少。这就是为什么人们使用这些更高级别的语言,尽管它们从理想的计算机语言角度来看更“糟糕”,而是更加以人为本。

答案 3 :(得分:13)

Monte Carlo integration是一种计算定积分的概率方法,无法保证返回正确的答案。然而,在现实世界的情况下,它返回的准确答案远远快于可证明正确的方法。

答案 4 :(得分:13)

Coppersmith–Winograd algorithm用于方阵乘法。其时间复杂度为天然乘法算法的O(n 2.376 vs。 O(n 3 )或 vs。Strassen algorithm,em> O(n 2.807 )。

来自维基百科的文章:

  

然而,与Strassen不同   算法,它没有在实践中使用   因为它只提供了一个优势   因为矩阵太大而不能   由现代硬件处理   (Robinson 2005)。

答案 5 :(得分:10)

此语句可应用于几乎所有并行算法。在计算的早期阶段他们没有经过深入研究的原因是,对于单个执行线程(想想单处理器),它们确实比渐近复杂性的小众所知的顺序对应物慢,小的 n ,或两者兼而有之。然而,在当前和未来的计算平台的背景下,可以使用少数(思考多核),几百(想想GPU)或几千(想想超级计算机)处理元素的算法将击败顺序版本的裤子在挂钟时间内,即使所有处理器花费的总时间/能量对于并行版本来说要大得多。

排序,图形算法和线性代数技术都可以通过承担额外的簿记,通信和运行时开销以节省成本来加速挂钟时间。

答案 6 :(得分:9)

通常可以选择容易quicksortparallelized的算法(如randomized)而不是缺乏这些品质的竞争算法。此外,通常情况下,当精确算法在approximate solution中产生指数运行时时,问题的Travelling Salesman Problem是可接受的。

答案 7 :(得分:8)

  

如果没有能够存储这些大型集合的计算机,那么这个例子就是答案。

据推测,该系列的尺寸为641K。


在负责各种飞机的结构和空气动力学代码的BAE SYSTEMS技术计算小组工作时,我们的代码库至少可以追溯到25年(并且有三分之一的员工在那里工作了很长时间)。

许多算法都针对16位大型机的性能进行了优化,而不是针对可扩展性。这些优化完全适用于20世纪70年代的硬件,但在替换它的32位和64位系统上的较大数据集上表现不佳。如果您选择的可伸缩性更差的东西在您当前正在处理的硬件上运行得更好,请注意这是一个优化,它可能在将来不适用。在编写那些20世纪70年代的例程时,我们在2000年代投入的数据大小是不切实际的。不幸的是,尝试从这些代码中提取一个清晰的算法然后可以实现以适应现代硬件并非易事。

如果没有沸腾的海洋,那么“所有实际情况”通常都是一个时间依赖的变量。

答案 8 :(得分:5)

存在一个用于确定素数的多项式时间算法,但在实践中,使用指数时间算法或执行足够的概率计算以获得足够的确定性总是更快。

答案 9 :(得分:5)

一个例子来自计算几何。由于Polygon triangulationChazelle具有最坏情况的O(N)算法,但由于实现的强硬性和巨大的常数,它几乎从未在实践中实现。

答案 10 :(得分:5)

不是很明显,但基于回溯的正则表达式与基于DFA的正则表达式的O(N)相比具有指数最坏情况,但是基于回溯的正则表达式几乎总是被使用而不是基于DFA的正则表达式。 / p>

编辑:(JFS)

Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...)

  

反向引用的力量   成本很高:最糟糕的   case,最着名的实现   需要指数搜索算法。

Regular Expression Engines

这种方法(DFA)效率更高,can even be adapted to allow capturing and non-greedy matching,但它也有一些重要的缺点:

  • 看似不可能
  • 背面参考也是不可能的
  • 正则表达式预编译更长,占用更多内存

从好的方面来说,以及避免最坏情况指数运行时间,DFA方法可以避免输入数据大小呈线性的最坏情况堆栈使用。

[3]:

答案 11 :(得分:4)

基数排序对于固定长度输入具有时间复杂度O(n),但更常使用快速排序,尽管较差的运行时运行时间,因为基数排序上的每元素开销通常要高得多。

答案 12 :(得分:4)

好的,考虑解决旅行销售人员问题。 ONLY 完美解决方案是测试所有可能的路线。然而,随着N增加,我们的硬件和时间限制变得不可能。所以我们想到了许多启发式方法。

这使我们回答你的问题。对于NP完全问题,启发式(更糟)比蛮力更好。这描述了“更糟的是更好”的情况。

答案 13 :(得分:4)

计算一组数字的中位数时,可以使用与快速排序非常相似的算法。你围绕一个数字进行分区,所有较大的分区都进入一侧,所有较小的分区进入另一侧。然后你扔掉一边并递归计算较大边的中位数。在最坏的情况下,这需要O(n ^ 2),但在平均情况下非常快(O(n)具有低常数)。

你可以得到最坏情况下的O(n)性能,常数约为40.这称为median of medians algorithm。在实践中,你永远不会使用它。

答案 14 :(得分:4)

如果我理解这个问题,那么你要求的算法在理论上更好但在所有情况下实际上都更差。因此,除非是错误的,否则不会指望它们实际被使用。

一个可能的例子是通用memoization。理论上,应该为所有可能的输入记忆所有确定性函数调用。这样,复杂的计算可以被简单的表查找所取代。对于广泛的问题,该技术有效地交换了存储空间的时间。但是假设有一个中央存储库,其中包含了所有人类计算机使用的所有可能功能的所有可能输入的结果。任何人在任何地方第一次进行计算,这将是最后一次。所有后续尝试都将导致表查找。

但是有几个原因我可以想到不这样做:

  1. 存储所有结果所需的内存空间可能不大。似乎所需位数可能超过宇宙中粒子的数量。 (但即使是估算这个数字的任务也是令人生畏的。)

  2. 构建一个有效的算法来记忆那个庞大的问题空间是很困难的。

  3. 随着客户数量的增加,与中央存储库的沟通成本可能会超过收益。

  4. 我相信你能想到其他问题。

    事实上,这种时间/空间权衡在实践中是不可思议的。理想情况下,所有数据都将存储在L1缓存中,但由于大小限制,您总是需要将一些数据放在磁盘上或(恐怖!)磁带上。推进技术减少了这些权衡的一些痛苦,但正如我上面提出的,存在限制。


    回应J.F. Sebastian的评论:

    假设我们不考虑通用的memoization存储库,而是考虑一个factorial存储库。并且它不会保留所有可能输入的结果。相反,它仅限于1N!的结果现在很容易看出任何执行阶乘的计算机都会从查找结果而不是计算中受益。即使计算(N+1)!,查找也将是一个巨大的胜利,因为该计算将减少到N!(N+1)

    现在为了使这个“更好”的算法更糟糕,我们可以增加N或增加使用存储库的计算机数量。

    但我可能不理解这个问题的一些微妙之处。他们正在考虑这个问题,我不断提出可以扩展的示例,直到他们不这样做。

答案 15 :(得分:3)

Mergesort与Quicksort

快速排序的平均时间复杂度为O( n log n )。它可以对数组进行排序,即空间复杂度为O(1)。

合并排序的平均时间复杂度为O( n log n ),但其空间复杂度更差:Θ( 名词的)。 (链表有一个特例)

由于最坏情况,快速排序的时间复杂度为Θ(n ^ 2)(即所有元素都落在每个轴的同一侧),而mergesort的最坏情况是O( n log n ),mergesort是库实现者的默认选择。

在这种情况下,我认为mergesort的最坏情况时间复杂度的可预测性胜过快速存储器要低得多的内存要求。

鉴于可以大大降低快速排序时间复杂性最坏情况的可能性(例如通过随机选择枢轴),我认为有人可能认为,除了快速排序的病态情况之外,mergesort更糟糕。

答案 16 :(得分:2)

尽管具有O(n 2 )复杂度的插入排序对于小集合(n <10)比任何其他排序算法更快。那是因为嵌套循环很小并且执行速度很快。许多具有sort方法实现的库(包括STL)实际上将它用于小型数据子集以加快速度。

答案 17 :(得分:2)

有一个O(n)算法用于从未排序的集合中选择第k个最大元素,但很少使用它而不是排序,当然是O(n logn)。

答案 18 :(得分:2)

我总是理解“更糟糕的是”这个术语与正确的解决方案相关联,这些解决方案非常复杂,其中存在一个相对容易理解的近似(或足够好)的解决方案。

这使得设计,生产和维护更容易。

答案 19 :(得分:1)

已经提出了蒙特卡罗整合,但更具体的例子是蒙特卡罗金融定价也是一个建议。这里的方法更容易编码,并且可以比其他方法做更多的事情,但它比有限差分要慢得多。

二维有限差分算法不实用,但20维定价执行很容易设置。

答案 20 :(得分:1)

The Spaghetti sort优于任何其他排序算法,因为它是O(n)设置,O(1)执行,O(n)提取排序数据。它在O(n)空间复杂度中完成了所有这些。 (整体表现:O(n)在时间和空间上都是。)然而,由于一些奇怪的(显而易见的)原因,没有人将它用于任何事情,更喜欢远低劣的O(nlogn)算法及其同类。

答案 21 :(得分:1)

有很多例子。

例如:

  1. Y-fast-trie的后继者/前任者的loglogu时间很复杂,但是常数很大,因此BST(即logn)更好。

  2. 在最坏的情况下,O(1)算法可以找到两个寄存器的最长公共前缀,但是它具有巨大的常数,因此最好使用平凡的logu算法(其中u是寄存器的最大值)。即使u是可观察宇宙中的原子数,使用logu解可能仍然更好。

  3. 与2相同,但用于查找寄存器的MSB。

  4. 融合树的查询复杂度为O(logn / loglogu),但具有巨大的常量(比所有前面的示例大得多的常量),BST可以在logn中实现相同的功能。因此,BST总是更好(除非您实际上拥有无限量的数据,这是不可能的)。

答案 22 :(得分:0)

Iterative Deepening

与使用alpha-beta pruning增加的普通深度优先搜索进行比较时,iterative deepening搜索与不良(或不存在)分支排序启发一起使用会导致扫描更多节点。然而,当使用良好的分支排序启发式时,由于α-β修剪的增强效果,树的大部分被消除。与时间或空间复杂性无关的第二个优点是早期建立对问题域的解决方案的猜测,并且随着搜索的进行猜测得到改进。这是第二个优势,使其在许多问题领域都具有吸引力。

答案 23 :(得分:0)

Quick-sort has worst case time complexity of O(N^2)! 
It is considered better than other sorting algorithms 
like mergesort heapsort etc. which have O(N log n) time complexity 
in the worst case.
The reason may be the 
1.in place sorting 
2.stability, 
3.very less amount of code involved.