算法的总的运行时间 = 运行的总代码行数。
时间复杂度,也就是指算法的运行时间(算法的速度指的并非时间,而是操作数的增速算法运行时间是从其增速的角度度量的)
空间复杂度和时间复杂度一样,反映的也是一种趋势,只不过这种趋势是代码运行过程中临时变量占用的内存空间,表示算法的存储空间与数据规模之间的增长关系。
大 O 复杂度表示法:
算法的执行效率,粗略地讲,就是算法代码的执行时间。我们假设每行代码执行的时间都一样,都是 1 个单位时间,从而算出一段代码总的执行时间为多少个单位时间,然后将公式中的低阶、常量、系数这三个不左右增长趋势的部分忽略,只记录最大量级的表示法。
用 T [n] 表示代码的执行时间,n 表示数据规模的大小,f (n) 表示每行代码执行的次数总和,算法执行时间的公式为:T [n]=O (f (n))
例:T (n)=2n+2 就可以记为 T (n)=O (n),T (n)=n^2 + 2 就可以记为 T (n)=O (n^2)
这就是大 O 时间复杂度表示法,大 O 时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,也叫做渐进时间复杂度,简称时间复杂度
时间复杂度的几条基本计算规则
1、基本操作,即只有常数项,认为其时间复杂度为 O (1)
2、顺序结构,时间复杂度按加法进行计算。比如一个算法复杂度为 O (n) 的结构和一个算法复杂度为 O (n2) 的结构相加,即 O (n2 + n),简化为 O (n^2)
3、循环结构,时间复杂度按乘法进行计算,比如外层循环为进行 n 次,内层为从 0 加到 100,那么内层的时间复杂度为 O (100),外层要进行 n 次,则总体的时间复杂度为 O (100n),简化为 O (n)。
4、分支结构,时间复杂度取最大值
主定理:
在时间复杂度的计算中,有一类问题的计算比较困难,这种问题就是递归问题,比如对于归并排序(Merge Sort)来说,每一层的复杂度为:
T(n) = 2T(n/2) + n
其中 T (n) 代表了当前层的时间复杂度,代表了将当前层的数据进行分解和将返回当前层的数据进行合并所需要的时间复杂度。
在递归问题中,时间复杂度计算的难点在于,如果要计算当前层,就需要首先得到下一层的时间复杂度,而为了计算下一层,又要计算下下层的时间复杂度,这就造成了计算困难。
为了能够快速得到递归算法的时间复杂度,可以使用主定理:
T(n) = aT(n/b) + f(n^d)
其中,n 是问题规模大小,a 是原问题的子问题个数,n/b 是每个子问题的大小,这里假设每个子问题有相同的规模大小,f (n^d) 是将原问题分解成子问题和将子问题的解合并成原问题的解的时间
常见时间复杂度:O (1) < O (logn) < O (n) < O (nlogn) < O (n^2) < O (n^3) < O (2^n) < O (n!) < O (n^n)
1、O(1):
O (1) 只是常量级时间复杂度的一种表示方法,并不是指只执行了一行代码。只要代码的执行时间不随着 n 的增大而增长,这样代码的时间复杂度我们都记作 O (1)。一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行代码,其时间复杂度也是 O (1)。
2、O(logn)、O(nlogn):
例: int i=1;
while(i<=n){i=i2;}
从代码中可以看出,变量的值从 1 开始取,每循环一次就可以乘以 2。当大于 n 时,循环结束。所以 2x=n,所以 x=log2n,这段代码的时间复杂度就是 O (log2n)。实际上,不管是以 2 为底,还是以 3 为底,我们可以把所有对数阶的时间复杂度都记为 O (logn)。
而 O (nlogn) 就是在循环内嵌套了一个时间复杂度为 O (logn) 的代码。O (nlogn) 是一种非常常见的算法时间复杂度。比如,归并排序、快速排序的时间复杂度都是 O (nlogn)
3、O(m+n)、O(mn):
例: for (int i=0;i<m;i++){
System.out.println("m");}
for(int j=0;j<n;j++){
System.out.println("n");}
从代码中可以看出,m 和 n 是表示两个数据规模。我们无法事先评估 m 和 n 谁的量级大,所以我们在表示复杂度的时候,就不能简单的利用加法法则,省略掉其中一个。所以上面的代码的复杂度是 O (m+n)。
这样我们的加法法则就不正确了,需要将加法规则改为:T (n)=T1 (m)+T2 (n)=O (m)+O (n)=O (m+n),但是乘法法则继续有效:T (n)=T1 (m) x T2 (n)=O (m) x O (n)=O (m*n)
平均时间复杂度:(算法完成工作平均需要多少基本操作)
指的是概率论中的加权平均值,也叫作期望值,所以平均时间复杂度的全称应该叫加权平均时间复杂度或者期望时间复杂度
公式:A (n) = ∑ I ∈ S P I t I A (n) = =I∈S∑PItI
其中 A (n) 表示平均时间复杂度,S 是规模为 n 的实例集,实例 i 的概率为 Pi, 算法对实例 i 执行的基本运算次数是 ti。