时间复杂度
原则
- 如果运行时间是常数量级,用常数1表示;
- 只保留时间函数中的最高阶项;
- 如果最高阶项存在,则省去最高阶项前面的系数。
场景一
给小灰一条长n寸的面包,小灰每3天吃掉1寸,那么吃掉整个面包需要几天?
1 | //T(n) = 3n,执行次数是线性的。 |
时间复杂度为:T(n) = O(n)
场景二
给小灰一条长16寸的面包,小灰每5天吃掉面包剩余长度的一半,第一次吃掉8寸,第二次吃掉4寸,第三次吃掉2寸……那么小灰把面包吃得只剩下1寸,需要多少天呢?
这个问题翻译一下,就是数字16不断地除以2,除几次以后的结果等于1?这里要涉及到数学当中的对数,以2位底,16的对数,可以简写为log16。
因此,把面包吃得只剩下1寸,需要 5 X log16 = 5 X 4 = 20 天。
如果面包的长度是 N 寸呢?
需要 5 X logn = 5logn天,记作 T(n) = 5logn。1
2
3
4
5
6
7
8
9
10//T(n) = 5logn,执行次数是对数的。
void eat2(int n){
for(int i=1; i<n; i*=2){
System.out.println("等待一天");
System.out.println("等待一天");
System.out.println("等待一天");
System.out.println("等待一天");
System.out.println("吃一半面包");
}
}
时间复杂度为:T(n) = O(logn)
场景三
给小灰一条长10寸的面包和一个鸡腿,小灰每2天吃掉一个鸡腿。那么小灰吃掉整个鸡腿需要多少天呢?
1 | //T(n) = 2,执行次数是常量的。 |
时间复杂度为:T(n) = O(1)
场景四
给小灰一条长10寸的面包,小灰吃掉第一个一寸需要1天时间,吃掉第二个一寸需要2天时间,吃掉第三个一寸需要3天时间…..每多吃一寸,所花的时间也多一天。那么小灰吃掉整个面包需要多少天呢?
答案是从1累加到10的总和,也就是55天。
如果面包的长度是 N 寸呢?
此时吃掉整个面包,需要 1+2+3+……+ n-1 + n = (1+n)*n/2 = 0.5n^2 + 0.5n。1
2
3
4
5
6
7
8
9//T(n) = 0.5n^2 + 0.5n,执行次数是一个多项式。
void eat4(int n){
for(int i=0; i<n; i++){
for(int j=0; j<i; j++){
System.out.println("等待一天");
}
System.out.println("吃一寸面包");
}
}
时间复杂度为:T(n) = O(n^2)
总结
四种时间复杂度究竟谁用时更长,谁节省时间呢?
1 | O(1)< O(logn)< O(n)< O(n^2) |
除了上述的四个场景,还有许多不同形式的时间复杂度,比如:
1 | O(nlogn), O(n^3), O(m*n),O(2^n),O(n!) |