一、相关
时间复杂度:执行当前算法所消耗的时间,记做即T(n) = O(f(n))
空间复杂度:对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))
总结:时间复杂度指的是语句执行次数,空间复杂度指的是算法所占的存储空间
二、时间复杂度
1.计算方法
- 用常数1代替运行时间中的所有加法常数
- 修改后的运行次数函数中,只保留最高阶项
- 去除最高阶项的系数
2.常见复杂度
复杂度由低到高示例
O(1):常数阶
public void Constant(int n){
int i = n+1;//仅需要一次计算,时间复杂度与n无关
System.out.println(i);
}
O(logn):对数阶
public static void logarithm(int n){
for (int i = 1;i < n;i = 2*i){
System.out.println(i);
}
}
在上面这个方法中,设执行次数为x,最后一次执行是余数为m,那么有:x^2 + m = n,在时间复杂度的计算中不考虑常数项,所以关于T(n)有:x^2 = n,那么x=log2n,也就是说此时T(n)=log2n
O(n):线性阶
public static void linear(int n){//线性阶
for (int i = 0;i<n;i++){//程序执行的次数与n的关系
System.out.println(i);
}
}
O(n^2):平方阶
public static void square(int n){//打印从1*1到n*n的乘法表
for (int i = 1;i<n+1;i++){
for (int m = 1;m<n+1;m++){
System.out.print(i+"*"+m+"="+i*m+" ");
}
System.out.println();
}
}
平方阶升级有k次方阶
O(2^n):指数阶(m是一个常数)
public static long index(int n){
if (n <= 1){
return 1;
}else {
return index(n-1)+index(n-2);
}
}
由程序可以看出,T(0)=T(1)=1,同时 T(n) = T(n - 1) + T(n - 2) + 1,这里的 1 是其中的加法算一次执行。显然 T(n) = T(n - 1) + T(n - 2) 是一个斐波那契数列,通过归纳证明法可以证明,当 n >= 1 时 T(n) < (5/3)^n,同时当 n > 4 时 T(n) >= (3/2)^n。所以该方法的时间复杂度可以表示为 O((5/3)^n),简化后为 O(2^n)。
3.最坏时间复杂度和平均时间复杂度
最坏情况下的时间复杂度称最坏时间复杂度。一般不特别说明,讨论的时间复杂度均是最坏情况下的时间复杂度。
平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,算法的期望运行时间。设每种情况的出现的概率为pi,平均时间复杂度则为sum(pi*f(n))
三、空间复杂度
1.相关
一般情况下是不考虑空间复杂度的,空间复杂度并不是指所有的数据所占用的空间,而是使用的辅助空间的大小,比如两个矩阵的运算,在中间设置了一个中间矩阵来保存一些数据,这些空间叫做空间复杂度。空间复杂度的运算非常麻烦,一般简单的算法空间复杂度都是O(1)。
2.常见空间复杂度
O(1)
public static void constant(int n){//常数阶
int i = n+1;
System.out.println(i);
}
无论n为何值,执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)
O(n)
public static void linear(int n){//线性阶
int[] m = new int[n];
}
简单的去理解,在这个方法中,所需要的空间与n是成线性关系的
四、总结
对于一个给定的算法,我们要做 两项分析。第一是从数学上证明算法的正确性,这一步主要用到形式化证明的方法及相关推理模式,如循环不变式、数学归纳法等。而在证明算法是正确的基础上,第二部就是分析算法的时间复杂度。算法的时间复杂度反映了程序执行时间随输入规模增长而增长的量级,在很大程度上能很好反映出算法的优劣与否。因此,作为程序员,掌握基本的算法时间复杂度分析方法是很有必要的。