我正在学习大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符号仅供参考。这可能会有所帮助!

大O----------------排序---------------复杂性

O(log N)     -Binary search      - logarithmic

O(N)         -Simple search      - Linear

O(N*log N)   -Quicksort          - loglinear 

O(2^N)       -recursive          - Exponential

O(N2)        -Selection sort     - directly proportional to the square of the input size.

其他回答

如果你正在寻找一个基于直觉的答案,我想为你提供两种解释。

想象一下一座很高的山,它的底部也很宽。要到达山顶,有两种方式:一种是一条围绕山顶螺旋延伸的专用通道,另一种是切割出的小露台状雕刻,以提供楼梯。现在,如果第一种方式在线性时间O(n)内到达,则第二种方式是O(logn)。想象一个算法,它接受整数n作为输入,并在时间上与n成比例地完成,那么它是O(n)或θ。

O(logn)指的是一个函数(或算法,或算法中的步骤),其工作时间与输入大小的对数成正比(大多数情况下通常以2为基数,但并不总是以2为底,在任何情况下,通过big-O符号*,这都是无关紧要的)。

对数函数是指数函数的倒数。换句话说,如果您的输入呈指数增长(而不是通常认为的线性增长),则函数呈线性增长。

O(logn)运行时间在任何一种分而治之的应用程序中都很常见,因为(理想情况下)每次都会将工作减半。如果在每一个除法或征服步骤中,你都在做恒定时间的工作(或不是恒定时间的,但随着时间的增长比O(log n)慢),那么你的整个函数就是O(log)。相当常见的是,每个步骤都需要输入线性时间;这将相当于O(n log n)的总时间复杂度。

二进制搜索的运行时间复杂性是O(logn)的一个例子。这是因为在二进制搜索中,通过将数组分成两半,并且每一步只关注一半,您总是忽略后面每一步的一半输入。每一步都是恒定的时间,因为在二进制搜索中,您只需要将一个元素与关键字进行比较,就可以确定下一步要做什么,而不管您考虑的数组在任何时候都有多大。因此,大约执行log(n)/log(2)步。

合并排序的运行时间复杂性是O(n log n)的一个例子。这是因为每一步都将阵列一分为二,总共约为log(n)/log(2)步。然而,在每一步中,您都需要对所有元素执行合并操作(无论是对n/2个元素的两个子列表执行一次合并操作,还是对n/4个元素的四个子列表执行两次合并操作都是无关紧要的,因为这增加了每一步对n个元素执行合并的必要性)。因此,总复杂度为O(n log n)。

*记住,根据定义,big-O表示法并不重要。同样,通过改变对数的基数规则,不同基数的对数之间的唯一差异是一个常数因子。

logb(n)是什么?

它是指在达到尺寸为1的截面之前,可以将长度为n的原木重复切成b等份的次数。

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

算法(第4版)

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

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

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

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

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

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

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

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

等等