我正在学习大O符号的运行时间和摊销时间。我理解O(n)线性时间的概念,这意味着输入的大小成比例地影响算法的增长。。。例如,二次时间O(n2)等也是如此。甚至是通过阶乘增长的算法,如置换生成器,其O(n!)次。

例如,以下函数为O(n),因为算法与其输入n成比例增长:

f(int n) {
  int i;
  for (i = 0; i < n; ++i)
    printf("%d", i);
}

类似地,如果存在嵌套循环,时间将为O(n2)。

但O(log n)到底是什么?例如,说一个完整的二叉树的高度是O(log n)是什么意思?

我确实知道(也许不是很详细)对数是什么,从这个意义上说:log10 100=2,但我不知道如何识别具有对数时间的函数。


当前回答

分而治之范式中的算法具有复杂性O(logn)。这里有一个例子,计算你自己的幂函数,

int power(int x, unsigned int y)
{
    int temp;
    if( y == 0)
        return 1;
    temp = power(x, y/2);
    if (y%2 == 0)
        return temp*temp;
    else
        return x*temp*temp;
}

从…起http://www.geeksforgeeks.org/write-a-c-program-to-calculate-powxn/

其他回答

分治算法通常具有运行时间的logn成分。这来自于输入的重复减半。

在二进制搜索的情况下,每次迭代都会丢弃一半的输入。需要注意的是,在Big-O表示法中,log是以2为底的log。

编辑:如上所述,对数基数并不重要,但当推导算法的Big-O性能时,对数因子将来自减半,因此我认为它是基数2。

我想补充一点,树的高度是从根到叶的最长路径的长度,节点的高度是该节点到叶的最大路径的长度。路径表示在两个节点之间遍历树时遇到的节点数。为了实现O(logn)时间复杂度,树应该是平衡的,这意味着任何节点的子节点之间的高度差应该小于或等于1。因此,树并不总是保证时间复杂度O(log n),除非它们是平衡的。实际上,在某些情况下,在最坏情况下,树中搜索的时间复杂度可能为O(n)。

你可以看看平衡树,比如AVL树。这项工作是在插入数据时平衡树,以便在树中搜索时保持(logn)的时间复杂度。

首先,我建议您阅读以下书籍:;

算法(第4版)

下面是一些函数及其预期的复杂性。数字表示语句执行频率。

以下Big-O复杂性图表也取自bigocheatsheet

最后,非常简单的展示展示了它是如何计算的;

剖析程序的语句执行频率。

分析程序的运行时间(示例)。

这个问题已经有了很多好的答案,但我相信我们真的错过了一个重要的答案,那就是图解的答案。

说一个完整的二叉树的高度是O(logn)是什么意思?

下图描述了一个二叉树。请注意,与上面的级别相比,每个级别包含的节点数量是两倍(因此是二进制的):

二进制搜索是一个复杂度为O(logn)的示例。假设图1中树底部的节点表示某个排序集合中的项目。二进制搜索是一种分而治之的算法,图中显示了我们需要(最多)4次比较才能找到我们在这个16项数据集中搜索的记录。

假设我们有一个包含32个元素的数据集。继续上面的图,发现我们现在需要5次比较才能找到我们正在搜索的内容,因为当我们乘以数据量时,树只增长了一层。结果,该算法的复杂性可以用对数级数来描述。

在一张普通纸上绘制对数(n)将生成曲线图,其中曲线的上升速度随着n的增加而减慢:

我一直以来在脑海中想象运行在O(log n)中的算法的最佳方式如下:

如果您将问题大小增加一个乘法量(即将其大小乘以10),则做功仅增加一个加法量。

将此应用于二叉树问题,这样您就有了一个很好的应用程序:如果将二叉树中的节点数加倍,则高度仅增加1(一个加法量)。如果再增加一倍,它仍然只增加了1。(显然,我假设它保持平衡)。这样,当问题规模成倍增加时,你的工作量不会加倍,而只是做了稍微多一点的工作。这就是为什么O(logn)算法非常棒的原因。