为什么两个O(n)程序是相同的?常数是否重要?

时间:2012-10-25 03:34:17

标签: algorithm complexity-theory

  

可能重复:
  Complexity. Why dont constants matter?

我有一个关于代码/算法复杂性的简单问题。我非常了解基本的复杂性概念,例如关于输入的增长顺序,为什么O(n)优于O(n ^ 2)等。但是,我不确定常量是否真的重要,因为它似乎对我来说,他们应该,但没有人会考虑他们或谈论他们。你能改进同样复杂的代码吗?让我们说我有一个代码复杂的代码,让我们说O(n)。让我们说这段代码在10分钟内运行以获得某些输入。如果我重复两次代码,现在代码运行20分钟,该怎么办?虽然复杂性是相同的,但10分钟内20分钟是一个大问题。无论相同的复杂性,这些事情是否重要?如果不是为什么?如果是,为什么?请解释。

6 个答案:

答案 0 :(得分:4)

在理论复杂性分析中,系数根本不重要。在实践中,它们很重要。这就是为什么几乎每个人仍然使用(指数复杂度)单纯形算法代替(多项式复杂度)内点算法来解决优化问题。

如果您正在进行算法分析并想知道O()行为,那么常量就无关紧要了。如果你想知道哪一段代码会针对特定范围的问题运行得更快,那么一切都很重要。

答案 1 :(得分:3)

我认为您正在将复杂性的真实概念与不同的性能示例相结合。根据复杂性,我们的意思是:如果n增长,处理步骤增长的顺序是什么。

比如说,您正在执行线性搜索,在这种情况下您的订单是O(n)。这里的含义是:如果n = 5,则需要5秒,然后n = 10,则需要10秒,即关系是线性的。

如果订单为O(5n),即n = 5,则同一搜索需要25秒,然后对于n = 10,则需要50秒,这没有区别。我仍然可以说,它的O(n)即直接依赖。

与O(n ^ 2)的排序算法相同。

在您的示例中,提到的改进确实很重要,但它不会改变复杂性的顺序,即关系。如果我们可以将处理时间减少两倍,这是一个很大的改进,前提是n是一个很高的数字,例如时间从20分钟减少到10分钟。如果你改变你的算法来改变与n的增长所花费的时间的关系,那么O(n)也会改变:)

答案 2 :(得分:1)

  

复杂性理论无关紧要,只对其感兴趣   函数如何随着输入大小的增加而缩放。

     

常量不会影响函数作为输入大小的行为方式   无论如何都要向无限远方向发展。

     

但是,如果你对实际运行某一部分感兴趣   代码,你很可能对一个大的不断开销感兴趣   函数如何针对较小的输入大小执行。

     

复杂性理论与实践的区别。

这是一个很好的答案。

Complexity. Why dont constants matter?

答案 3 :(得分:1)

当然,如果你制作的算法速度是它需要的两倍,那就很重要了。关键是,我们关注算法在“n”方面的表现,因为“n”有可能非常大。

我们来看一个实际的例子。假设您有n个项目的列表。您的算法会迭代列表一次。这是顺序n。如果它在列表上重复两次,则可能需要更长时间,而且速度会更慢 - 如果不必要,则不应该这样做。

但是,从长远来看,拥有n ^ 2算法比2 * n算法具有更大的影响。随着n越来越大,n ^ 2和2 * n之间的差异越来越大。

所以回答你的问题,是的,当程序运行速度慢两倍时,这很重要。但如果它指数速度慢,那就更重要了。这就是我们关心Big-Oh的原因。但是对速度的任何改进显然都会对你的程序有所帮​​助。

答案 4 :(得分:1)

理论与实践之间存在很大差异。有一些要考虑的要点:

  • 对于实际实现,常量可能不明确。您通常无法从给定的实现中确定这些常量。举例来说,对于同一个问题,你有两个O(N)算法,一个需要2N操作,第二个只需要N个操作。有人可能会假设具有N个操作的那个运行得更快,但情况可能并非如此。我们可能有2N个操作,由于更好的缓存或pipline使用等,每个操作只需要1个周期,而另一个算法可能需要N个操作,每个操作4个周期。因此具有更多操作的算法可能仍然更快。在不同的硬件上,这可能看起来非常不同。因此,除非您了解确切的硬件,否则理论分析是一个非常好的指南。在真正的硬件上,通常交互是如此错综复杂,只有基准测试会给你一个很好的提示。

  • 对于实时系统,情况又是如此。这里通常对最坏情况执行时间(WCET)感兴趣,该时间指的是算法可能采用的实际时间。在这种情况下,常数很重要。然而,在这种情况下,问题的大小也是已知的(通常是来自几个传感器的一组输入),因此分析有很大不同。

  • 硬件的影响可能会变得如此之大,以至于理论上看起来更糟的算法实际上可能胜过看起来好得多的算法,至少对于所有相关的问题大小而言。对于使用树(通常在理论上更好)的算法与使用平面阵列结构的算法(理论上通常更糟)的情况通常是这种情况。通常,平面阵列更好,因为它可以更有效地缓存。有时可以使用两者中最好的,例如,当将堆实现为数组时(这几乎总是优于已排序的树)。

答案 5 :(得分:0)

当比较O(n)和O(n ^ 2)时,n增长常数将开始变得无关紧要。即使常数很大,这应该是非常明显的。

没有提到常数的原因是复杂性的顺序更重要。一旦你知道算法是线性时间,你就可以在计算细节时自己检查斜率。

当你有两个O(n)常量的程序时,决定哪个更好是重要的。然后,您必须更详细地分析算法。