我正在学习大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,但我不知道如何识别具有对数时间的函数。


当前回答

如果你在图形计算器或类似的东西上绘制一个对数函数,你会发现它的上升速度非常慢——甚至比线性函数还要慢。

这就是为什么对数时间复杂度算法备受追捧的原因:即使对于真正大的n(例如,假设n=10^8),它们的性能也超出了可接受的范围。

其他回答

这仅仅意味着该任务所需的时间随着log(n)的增加而增加(例如:n=10时为2s,n=100时为4s,…)。请阅读维基百科关于二进制搜索算法和大O符号的文章以了解更多的精度。

这两种情况需要O(log n)时间

case 1: f(int n) {
      int i;
      for (i = 1; i < n; i=i*2)
        printf("%d", i);
    }


 case 2  : f(int n) {
      int i;
      for (i = n; i>=1 ; i=i/2)
        printf("%d", i);
    }

实际上,如果您有一个n个元素的列表,并从该列表中创建一个二叉树(就像在除法和征服算法中一样),您将一直除以2,直到达到大小为1的列表(树叶)。

在第一步,你除以2。然后,您有2个列表(2^1),将每个列表除以2,因此您有4个列表(2*2),然后再进行一次除法,您有8个列表(3^3),依此类推,直到列表大小为1

这给出了一个等式:

n/(2^步)=1<=>n=2^步<=>lg(n)=步

(取每边的lg,lg为对数基数2)

你可以通过说时间与N中的位数成正比来直观地想到O(log N)。

如果一个操作对输入的每个数字或位执行恒定的时间工作,则整个操作所花费的时间将与输入中的数字或位的数量成比例,而不是与输入的大小成比例;因此是O(log N)而不是O(N)。

如果一个操作做出一系列恒定的时间决定,每个决定将要考虑的输入的大小减半(减少3、4、5…的因子),那么整个过程将花费与输入大小N的对数基2(基3、基4、基5…)成比例的时间,而不是O(N)。

等等

如果你在图形计算器或类似的东西上绘制一个对数函数,你会发现它的上升速度非常慢——甚至比线性函数还要慢。

这就是为什么对数时间复杂度算法备受追捧的原因:即使对于真正大的n(例如,假设n=10^8),它们的性能也超出了可接受的范围。