算法速度顺序

时间:2009-02-10 13:14:11

标签: algorithm performance big-o performance-estimation

有时我完全被愚弄试图用O(x)表示法来估计算法的速度,我的意思是,当命令是O(n)或O(mxn)时我真的可以指出,但对于那些是O的那些(lg(n))或O(C(权力n))我认为我在那里遗漏了一些东西...... 那么,您可以通过快速忽略算法轻松估算出哪些提示和技巧?

作为我正在寻找的一个例子,这里有一些容易的(可能是错的,但是尽我所能):

  • O(n):如果有一个从1到n的简单循环(或其中几个,但没有嵌套。
  • O(mxn):另一个嵌套循环,其中限制为m和n。

提前致谢。

8 个答案:

答案 0 :(得分:7)

递归,分而治之的算法通常是O(logN)。循环分而治之的算法是O(NlogN)。

答案 1 :(得分:7)

这是一篇可能有帮助的博文:

The cost of breaking things down and putting them back together

该帖子解释了使用big-O订单的“主定理”。

答案 2 :(得分:4)

O(lg(n)):如果你的问题在算法的每一步都变小了一定比例的n(通常为n / 2),并且每一步都会做一定量的工作。二进制搜索是一个很好的例子,因为每个步骤通过做一定量的工作将你的问题大小减少一半(计算中点并进行一次比较)。

请注意,n位于该比例的 top 上。这与您在每一步减少1 / n的问题大小不同。 :)

答案 3 :(得分:1)

如果您正在寻找快速方式来估算算法的运行时间,其他答案都很好。如果您想要更详细的答案,我建议您查看“Master theorem”。在German article中,有一个很好的表格。

编辑:John D. Cook对主定理进行了很好的回顾,请参阅链接他的答案。

答案 4 :(得分:1)

Big O Notation上的Wikipedia article有一个很好的orders of common functions图表。

答案 5 :(得分:1)

算法的渐近复杂性在实践中很重要,以下是我在查看我的或其他人的代码时使用的一些经验法则。通常实际的计算机算法是许多变量和非平凡数据结构的函数,但让我们假设(仅用于说明)我们的算法f基本上采用单个整数X作为其参数,并且我们希望找到f的渐近复杂度。 X.假设f(0)是微不足道的。那么一般来说:

  • 从0到X的每个嵌套循环都会向X添加一个指数,因此两个循环(一个嵌套在另一个循环中)给出X ** 2(二次)。
  • 如果f(X)尾递归地调用f(X-1),它通常对应于迭代,即单个外循环(O(X))。
  • 我已经看到了作者想要迭代的例程,但是从0..X和X-1的尾递归都进行了迭代。这些导致二次行为(O(X ** 2))
  • 如果f(X)调用f(X-1)两次或更多次,则会产生指数算法,并从中获得O(2 ** X)。
  • 如果f(X)两次调用f(X / 2),则它与单次迭代的复杂性相对应(它是一种分而治之的算法)。 (根据细节产生O(X log X)或O(X),但我意识到我认为它仍然是一次迭代。)
  • 如果f使用已正确实现的任何有序数据结构(有序集,优先级堆等),并且算法大致将X对象添加到数据结构,则操作为O(log X)。因此,如果循环中发生了一定数量的数据结构操作,那么就得到O(X * log X)。
  • 如果未正确实施有序数据结构,则可以为各个操作获取O(X)而不是O(log X)。

一些特殊情况:

  • 通过追加增加字符串或内存区域的算法,在许多语言中都会产生O(X ** 2)开销,例如

    for (i = 0; i < X; i++) { s += "foo"; } // quadratic
    
  • 这个典型的嵌套循环也有X ** 2开销:

    for (i = 0; i < X; i++) { for (j = 0; j < i; j++) { ... } } // quadratic
    
  • 像std :: set和std :: map这样的C ++ STL容器几乎对所有操作都有O(log X)开销

  • strlen(s)和其他类似的计数算法,当它们返回X时有O(X)开销
  • memcpy等导致O(X)
  • 存在复杂性危险操作,例如通过链接列表中的等式比较来擦除元素,从而产生O(X)或更差
  • 使用基于模板的容器时,请确保比较,排序等运算符快速且没有隐藏的复杂因素
  • 如果使用引用计数,如果删除对长度为X的引用的链接列表的最后一个引用,则删除引用可能是最坏情况的O(X)操作
  • 如果复制对象的例程是非常重要的,例如,复制面向对象语言中的复杂数据结构会产生奇怪的渐近复杂性。更新全局对象集

只需2美分!希望这有帮助!

答案 6 :(得分:1)

通常会出现类似O(logN)的内容,因为数据的大小为N,但它是有组织的,例如在树的深度为logN的树中。如果典型的搜索涉及从根到叶(在更坏的情况下),那么很容易看出算法将是O(logN)。

没有严格的规则 - 您只需要查看每个案例,找出最糟糕的情况,并计算出成本是多少。

答案 7 :(得分:0)

我不是回答自己问题的忠实粉丝,但今天我发现了这个并提醒我这个问题。

http://bigocheatsheet.com/