请问怎么计算时间复杂度?

请问怎么计算时间复杂度?

时间复杂度,说白了就是算法跑的多快。

这个多快,不是说算法代码真正的运行时间,而是代表着一种趋势,一种随着数据集的规模增大,算法代码运行时间变化的一种趋势。

刚好我前几天回答过相关的问题,这里我就再来说一下吧。

内容很长,记得先点赞收藏,再看不迷路呦~

首先我先来手把手的带你算两次时间复杂度。

代码 1

这段代码我会从最开始一点点带你来。

第 2 行需要运行 1 次 ,第 4 行需要运行 n 次,第 5 行和第 6 行分别需要运行 n² 次。所以总的运行次数 f(n) = 1 + n + 2n²。

当 n 为 5 的时候,f(n) = 1 + 5 + 2 * 25,当 n 为 10000 的时候,f(n) = 1 + 10000 + 2 * 100000000,当 n 更大呢?

这个时候其实很明显的就可以看出来 n² 起到了决定性的作用,像常数 1,一阶 n 和 系数 2 对最终的结果(即趋势)影响不大,所以我们可以把它们直接忽略掉,所以执行的总步数就可以看成是“主导”结果的那个,也就是 f(n) = n²。

自然代码的运行时间 T(n) = O(f(n)) = O(n²)。

代码 2

上面这段代码是求三部分的和,经过之前的学习应该很容易知道,第一部分的时间复杂度是 O(n),第二部分的时间复杂度是 O(n²),第三部分是 O(n³)。

正常来讲,这段代码的 T(n) = O(n) + O(n²) + O(n³),按照我们取“主导”部分,显然前面两个小弟都应该直接 pass,最终 T(n) = O(n³)。

通过这几个例子,聪明的你肯定会发现,对于时间复杂度分析来说,只要找起“主导”作用的部分代码即可,这个主导就是最高的那个复杂度,也就是执行次数最多的那部分 n 的量级。

下面我再来说一下题主在描述中提的几个时间复杂度。

算法学习过程中,我们会遇到各种各样的时间复杂度,但纵使你代码七十二变,几乎也逃不过下面这几种常见的时间复杂度。

上表的时间复杂度由上往下依次增加,O(n) 和 O(n²) 前面已经讲过了,O(2n) 和 O(n!) 效率低到离谱,以后不幸碰到我再提一下,就不再赘述。

下面主要来看剩下几种最常见的时间复杂度。

O(1)

O(1) 是常数时间复杂度。

在这你要先明白一个概念,不是只执行 1 次的代码的时间复杂度记为 O(1),只要你是常数,像 O(2)、O(3) ... O(100000) 在复杂度的表示上都是 O(1)。

比如像上面这段代码,它运行了 3 次,但是它的时间复杂度记为 O(1),而不是 O(3)。

因为无论 n 等于多少,对于它们每行代码来说还是只是执行了一次,代码的执行时间不随 n 的变化而变化。

O(logn)

O(logn) 是对数时间复杂度。首先我们来看一段代码:

根据之前讲的,我们先找“主导”,在这主导就是第 4 行代码,只要算出它的时间复杂度,总的时间复杂度就知道了。

其实很简单,上面的代码翻译一下就是初始化 dogegg = 1, 乘上多少个 2 以后会 ≥ n。

假设需要 x 个,那么相当于求:

即:

所以上述代码的时间复杂度应该为 O(log2n)。

但是对于对数复杂度来说,不管你是以 2、3 为底,还是以 10 为底,通通记作 O(logn),这是为什么呢?

这就要从对数的换底公式说起。

根据换底公式,log2n 可以写成:

对于时间复杂度来说:

所以在对数时间复杂度中我们就忽略了底,直接用 O(logn) 来表示对数时间复杂度。

O(nlogn)

O(nlogn),真的是很常见的时间复杂度,像后面会学到的快速排序、归并排序的时间复杂度都是 O(nlogn)。

如果只是简单看的话是在 logn 外面套了层 for 循环,比如像下面这段代码:

当然像上面这种 stupid 代码一般人不会写,我也只是举个例子给大家看,我是狗蛋,大家千万不要以为我是傻狗。