持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情
一些重要的复杂性类
下面列出了一些最常见的大O(和θ)实例。在每种情况下,n 都是函数输入大小的度量。
0(1) 表示恒定的运行时间。
o(1og n) 表示对数运行时间。o(n)表示线性运行时间。
·o(n 对数 n) 表示对数线性运行时间。
o(nk) 表示多项式运行时间。请注意,k 是一个常量。
·o(c“) 表示指数运行时间。在这里,一个常数被提升到一个基于输入大小的幂。
恒定的复杂性
这表明渐近复杂性与输入的大小无关。这个类中很少有有趣的程序,但所有程序都有适合这个类的部分(例如,找出Python列表的长度或乘以两个浮点数)。恒定的运行时间并不意味着代码中没有循环或递归调用,但它确实意味着迭代或递归调用的次数与输入的大小无关。
对数复杂度
此类函数的复杂性随着至少一个输入的对数而增长。例如,二进制搜索在所搜索列表的长度上是对数的。(我们将在第12章中介绍二进制搜索并分析其复杂性。顺便说一句,我们不关心对数的基数,因为使用一个基数和另一个基数之间的差异只是一个常数乘法因子。例如,0(1og2(x)) = 0(1og2(10)*10g10(x))。有许多有趣的函数具有对数复杂性。考虑
由于此代码中没有函数或方法调用,因此我们知道我们只需要查看循环即可确定复杂性类。只有一个循环,所以我们唯一需要做的就是表征迭代次数。这可以归结为我们可以在得到之前使用 // (楼层除法) 将 i 除以 10 的次数。
o 的结果。因此,int_to_str的复杂性在于 o(log(i))。更准确地说,它是阶 θ(log(i)),因为 log(i) 是一个紧密的边界。
使用int_to_str将 n 转换为字符串的复杂性是阶数 θ(log(n)),int_to_str返回长度为 log(n) 的字符串。for 循环将执行订单 θ(1en(string_rep)) 次,即订单 θ(1og(n)) 次。将它们放在一起,并假设表示数字的字符可以在常量时间内转换为整数,程序将在与θ(1og(n))+ θ(1og(n))成比例的时间中运行,这使得它的顺序为θ(1og(n))。
线性复杂性
许多处理列表或其他类型的序列的算法都是线性的,因为它们接触序列的每个元素的次数是常数(大于 o)。
许多处理列表或其他类型的序列的算法都是线性的,因为它们接触序列的每个元素的次数是常数(大于 o)。
例如,考虑
此函数在 s 的长度上是线性的,即 θ (1en (s))。
当然,程序不需要有一个循环就具有线性复杂性。考虑
此代码中没有循环,因此为了分析复杂性,我们需要确定进行了多少递归调用。一系列的电话很简单
这个级数的长度,以及函数的复杂性,是阶数θ(x)。
到目前为止,在本章中,我们只研究了代码的时间复杂性。这对于使用恒定空间量的算法来说很好,但阶乘的这种实现不具有该属性。正如我们在第 4 章中所讨论的,阶乘的每个递归调用都会导致分配一个新的堆栈帧,并且该帧继续占用内存,直到调用返回。在递归的最大深度下,此代码将分配 x 个堆栈帧,因此空间复杂度为 o (x) 。
空间复杂性的影响比时间复杂性的影响更难理解。一个程序需要一分钟还是两分钟才能完成,这对用户来说是非常明显的,但是它是否使用一兆字节或两兆字节的内存对用户来说是不可见的。这就是为什么人们通常更关注时间复杂性而不是空间复杂性。当程序需要的空间多于运行该程序的计算机的快速内存中的可用空间时,会发生异常。