今天用10分钟的时间,介绍下算法中最基本的一个概念,时间复杂度.
简单来说,就是一个算法,后者一个方法或者函数,执行时需要多长时间.
举个例子来说
int i = 100 * 10;
这个赋值语句,只执行一次,那他的时间复杂度就是O(1)
例2:
public void fun1(int n) {
int[] array = new int[n]; // 执行1次
for (int i = 0; i < array.length; i++) { // 执行 N 次
System.out.println(i); // 执行 N 次
}
}
这个算法中,标记的时间是将CPU执行每条语句的真正时间忽略为1,
所用时间就是T(n)=1 + N + N = 2 * N + 1
根据时间复杂度的基本规则:去掉常数,保留最高阶
最后结果为T(N)=O(2 * N + 1) = O(N)
也因为上述规则,时间复杂度,也称为渐进的时间复杂度.
我们再看个稍微复杂的列子
例3:
public void fun2(int n) {
int[] array = new int[n]; // 执行1次
for (int i = 0; i < array.length; i++) { // 执行 N 次
for (int j = 0; j < n; j++) {
System.out.println(i); // 执行 N * N 次
}
}
}
根据基本规则,我们之间看最高阶部分即可,也就是嵌套循环内部逻辑
T(N)=O(N^2)
例4:
public void fun3(int n){
int count = 1;
while (count < n){
count = count * 2;
}
}
这个方法中,可以看到执行次数,并不能直观的看出来.方法中while循环中,每执行一次就更接近N一分,当执行一定次数后,大于n了,退出循环.现在假设执行次数为X,也就是2^X>N,对应的X=log2(N),时间复杂度就是O(log2(N)).这个方法与前2个列子的区别在于他执行时会跳过很多数,执行的次数比O(N)少很多,也意味着,这个方法的时间复杂度要优于O(N)的.
例5:
long fun4(int n) {
if (n <= 1) {
return 1;
} else {
return fun4(n - 1) + fun4(n - 2);
}
}
这是著名的斐波那契数列函数,显然执行次数,T(0)=T(1)=1,同时 T(n)=T(n - 1)+T(n - 2)+1,最后通过归纳证明,时间复杂度可以简化为O(2^N)
下面是常用的时间复杂度表达式和术语,
阶 | 对应术语 | |
---|---|---|
1 | O(1) | 常数阶 |
2 | O(N) | 线性阶 |
3 | O(N^2) | 平方阶 |
4 | O(logN) | 对数阶 |
5 | O(NlogN) | NlogN阶 |
6 | O(N^3) | 立方阶 |
7 | O(2^N) | 指数阶 |
以上,简单的介绍了时间复杂度的相关概念和算法.