我正在学习大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(n)内到达,则第二种方式是O(logn)。想象一个算法,它接受整数n作为输入,并在时间上与n成比例地完成,那么它是O(n)或θ。

其他回答

但O(log n)到底是什么?例如,如果一个>完整二叉树的高度是O(logn),这意味着什么?

我会将其重新表述为“完整二叉树的高度是logn”。如果一步一步向下遍历,计算完整的二叉树的高度将是O(logn)。

我无法理解如何用对数来识别函数时间

对数本质上是幂的倒数。因此,如果函数的每个“步骤”都在从原始项集中删除一个元素因子,那就是对数时间算法。

对于树的示例,您可以很容易地看到,当您继续遍历时,逐步降低节点级别会减少指数级的元素数量。浏览按姓名排序的电话簿的流行示例基本上等同于遍历二进制搜索树(中间页面是根元素,您可以在每个步骤中推断是向左还是向右)。

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

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

这两种情况需要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);
    }

在信息技术中,它意味着:

  f(n)=O(g(n)) If there is suitable constant C and N0 independent on N, 
  such that
  for all N>N0  "C*g(n) > f(n) > 0" is true.

看来这个符号主要是从数学中提取出来的。

本文引用了一句话:D.E.Knuth,《大OMICRON、大OMEGA和大THETA》,1976年:

基于这里讨论的问题,我建议SIGACT以及计算机科学和数学期刊的编辑,采用上面定义的符号,除非有更好的替代方案很快就会发现。

今天是2016年,但我们今天仍然使用它。


在数学分析中,这意味着:

  lim (f(n)/g(n))=Constant; where n goes to +infinity

但即使在数学分析中,有时这个符号也用于表示“C*g(n)>f(n)>0”。

我从大学里就知道,这个符号是由德国数学家朗道(1877-1938)创造的

O(logn)是衡量任何代码运行时性能的多项式时间复杂度之一。

我希望你已经听说过二进制搜索算法。

假设您必须在大小为N的数组中找到一个元素。

基本上,代码执行如下N不适用于2不适用于4N/8…等

如果你把每一级所做的所有工作相加,你将得到n(1+1/2+1/4….),等于O(logn)