关于时间复杂度我会总结:
- 算法优劣评估的核心指标?
- 什么是时间复杂度?
- 什么是常数项?
- 通过选择排序来深刻理解时间复杂度
- 额外空间复杂度
注意: 希望大家不要着急,我们先从抽象的开始,待会带大家慢慢的走向具象,刚开始的定义不懂没关系,接下来的例子才是精彩的开始。
算法优劣评估的核心指标?
首先我们需要明确什么是算法优劣评估的核心指标,只有知道了这个你才能够自己动手去评估你写的算法到底好还是不好。
主要包括两个东西,第一个是时间复杂度(流程决定),第二个是空间复杂度(流程决定),这两个都是由你实现算法的流程决定。常数项时间(实现细节决定),这个在笔试甚至在ACM的竞赛中都没有那么重要,所以关于常数项的部分大家不必过度纠结。
什么是时间复杂度?
首先我们要知道算法中所说的操作数中的操作指的是常数时间的操作(关于这个具体的待会会详细讲解,大家不要着急,且听我娓娓道来)。
算法时间复杂度定义:确定算法流程的总操作数量与样本之间的表达式关系。
算法的时间复杂度只看表达式的最高阶的部分
时间复杂度的作用:时间复杂度是指执行算法所需要的计算工作量,并不代表程序的执行时间,而是操作步骤。
算法的时间复杂度的表示符号是用 大O(big O)表示,函数输入的数据量用n来表示,比如:选择排序的时间复杂度为。
同时需要知道的是在同一个算法,不同的输入算法的表现是不一样,时间复杂度一般是一 最差 的时间复杂度为标准。
先给大家看看时间复杂度的排序 (从左到右,时间复杂度由差到好):(扫过去就行了)
什么是常数项?
先给出一个定义:如果一个操作的只想时间不以具体样本量为转移,每次执行时间都是固定时间,称这样的操作数为常数时间操作。(这个定义倒是挺重要的,不过没理解没关系,耐心往下看)
我们先来几个栗子,让大家更具体化一点什么是常数时间操作:
- 常见的算术运算(+、-、*、/、% 等),不管计算加号两边的数有多大,加法的计算时间都是一样的
- 常见的位运算(>>、>>>、<<、|、&、^ 等)要注意哦,位运算比除法运算快,所以如果能用位运算就用位运算
- 赋值、比较、自增、自减
- 数组寻址操作,像是hashmap寻找key的时候就是O(1)的时间复杂度,O(1)就代表的是常数时间的操作
总之,执行时间固定的操作都是常数时间的操作
反之,执行时间不固定的操作,都不是常数时间的操作
小问题:如果在一个算法中,给一长度为32的数组循环填满,执行n次,那么这个给长度为32循环填满是常数时间的操作还是不是呢?
在文章结尾会有答案哦。
接下来我带大家通过对于选择排序算法的复杂度计算,来理解时间复杂度是如何估计
例如 : 对于选择排序的算法,
首先简单说一下选择排序的算法思路,假设输入的数据规模是n,选择排序会遍历整个list一遍然后找到最小的数字和第一个数字进行交换,然后从剩下的n - 1个数字中找到最小的,然后和第二个数字进行交换,直到交换到第n个数字,就排序完成了。
接下来我们通过快速排序来深刻理解时间复杂度:
如果我们输入一个整数列表 [4, 3, 2, 1] 它需要首先找到列表中最小的数字,也就是 1,然后再将1与前面的作对比,将移动到一个
合适的位置 [ 1, 4, 3, 2 ],然后需要找到除1之外最小的数字,也就是2,然后将它移动到合适的位置,得到数组 [ 1, 2, 4, 3 ] 剩下
的以此类推,我们将会得到一个升序的列表[ 1, 2, 3, 4]。
因此,如果假设输入的数据的规模是n,输入的数据是倒叙的,在选择排序里面我们找到最小的第一个数字我们需要花费时间 n ,
找到第二个需要时间 n - 1,找到第三个需要时间 n - 2,剩下的以此类推,只要把这个所有的操作加起来就是我们的选择排序针对输入样本量为n的情况的时间复杂度。同时我们不难看出这些时间的加和是一个等差数列,因此我们通过等差数列的求和公式我们可以得到选择排序的时间复杂度是
,这就是选择排序的最差的时间复杂度。
但是,为什么实际上选择排序时间复杂度为
,而不是
?
因为在对算法时间复杂度的进行估计的时候,我们只记录时间最高阶项!
只记录最高阶项,意味着什么?
意味着时间复杂度为的算法,不管他的常数项和低阶项有多差,有多大,在输入很大的情况下,永远都没有时间复杂度为O(n)的算法好。
所以需要记住下面这个时间复杂度的排序 (从左到右,时间复杂度由差到好):
只有在两个算法时间复杂度同样的时候我们才需要去比较他的常数项,例如:归并排序和快排,他们平均的时间复杂度都是,但是实际上快排是比归并排序快的,因为快排在常数项上面的时间复杂度是由于归并排序的。
额外空间复杂度是什么?
你要时间下一个算法流程,在实现算法流程的过程中,你需要开辟一些空间来支持你的算法。
如果不理解那我们来例子:
作为出入参数的空间,不算做额外空间。
作为输出结果的空间,不算做额外空间。
因为这些都是必要的、和显示目标有关,所以不算。
除此之外,你的流程如果还需要开辟空间才能让你的流程继续走下去。这部分空间就是额外空间。
如果你的流程只需要开辟优先几个变量,额外空间复杂度就是O(1)。
例如上面的插入排序,只需要用两个变量,一个变量用来记录最小数的下表,另一个变量用来记录需要替换的数的下标。
小问题答案:
不是,因为给32位的数组循环填满的时间是固定的。
Reference: https://italk.mashibing.com/course/detail/cour_00004003