时间复杂度
先抛出结论:时间复杂度是什么?
时间复杂度是用来衡量代码的执行速度的。
时间复杂度 = 时间的增长趋势
注意:时间复杂度只是表示一个趋势,并不是精确值
我们通过接下来的几个示例,就能更深刻理解上面的结论
1.案例
示例1
function fn() {
console.log('我被打印了一次') //执行一次
return 0 //执行一次
}
我们可以看出,以上代码在调用1次函数fn时,内部一共执行2次语句。
那么我们用公式表示:
T(n) = 2
n:输入数据的大小或数据量
T(n):当输入为n时,某段代码的总执行次数
或许现在你还仍然有点模糊,不过没关系,我们再看下面一个示例
示例2
从以上代码可以看出,调用1次函数fn2,就会执行1 +(n+1)+ n + n + 1,也就是3n+1次,用公式表达为:T(n) = 3n+1
但是,作为衡量代码的执行速度的依据,当代码比较多的时候,使用T(n)就有点麻烦了,我们还要一条条语句去数,而且当函数调用函数的时候运算起来也很麻烦,所以算法一般使用T(n)简化的估算值
来衡量代码执行的速度,这个简化的估算值就叫做——时间复杂度
2. T(n)如何转换为时间复杂度
2.1 情景一
T(n) = 常数 ——> 1
如果T(n)等于一个常数,那么时间复杂度就是1,换成公式写法:O(1)
示例1的执行次数T(n) = 1,那么它的时间复杂度就为1,换成公式写法:O(1)
2.2 情景二
T(n) = 常数 × n + 常数 ——> n
我们可以直接去掉加号后面的常数
,和加号前面的常数
(因为随着n的增大,常数的影响力就会越来越小,也就相当于不存在,所以可以直接省略),那么时间复杂度就为n
,换成公式写法:O(n)
示例2的执行次数T(n) = 3n + 3,那么它的时间复杂度就为n,换成公式写法:O(n)
2.3 情景三
那么对于多项式
T(n) = 5n³ + 6666n² + 233
我们只需要保留n的最高次项
,也就是保留n的次方数最大的那一项,因为随着n的增大,后面的项的增长远远不及n的最高次项大,所以可以直接忽略低次项,接着系数5也要直接去掉
,因此时间复杂度就是n³
,换成公式写法:O(n³)
3.总结
T(n)是不是常数:
- 是:时间复杂度O(1)
- 否:时间复杂度为O(保留T(n)的最高次项并去掉最高次项的系数)
4.归纳几个常见函数的时间复杂度
4.1
function fn() {
console.log('我们遇到什么困难都不要怕!')
console.log('微笑地面对他!')
console.log('消除恐惧的最好办法就是面对恐惧!')
console.log('坚持 才是胜利!')
console.log('加油 奥利给!!!')
}
以上代码没有循环,只有一条条语句,因此时间复杂度是O(1)
4.2
function fn2(n) {
for(let i = 0;i < n; i++) {
console.log('hello')
}
}
像函数fn2这样,只有一个循环,那么它的时间复杂度就是O(n)
4.3
function fn3(n) {
for(let i = 0; i < n; i++) {
for(let j = 0; j < n; j++) {
console.log('鸡你太美~')
}
}
}
fn3函数,内部循环复杂度为n,外部循环则是n × n,因此时间复杂度就位O(n²)
.
以此我们类推,有a重循环,时间复杂度就为O(n^a)
4.4
function fn4(n) {
if(n>100) {
for(let i = 0; i < n; i++) {
for(let j = 0; j < n; j++) {
console.log('鸡你太美~')
}
}
} else {
for(let i = 0; i < n; i++) {
console.log('哒哒哒')
}
}
}
如果加了if判断,那么时间复杂度是以时间最长的分支来判断
,因此以上代码的时间复杂度仍然为O(n²)