一、时间复杂度
当问题规模即要处理的数据增长时,基本操作要重复执行的次数必定也会增长,那么我们关心的是这个执行次数以什么样的数量级增长。
我们用O表示一下常见的时间复杂度量级:
- 常数阶O(1)
- 线性阶O(n)
- 对数阶O(logn)
- 线性对数阶O(nlogn)
- 平方阶O(n2)
当然还有指数阶和阶乘阶这种非常复杂度量级,我们就不讨论了。
二、各时间复杂度分析
O(1):
传说中的常数阶的复杂度,这种复杂度无论数据规模n如何增长,计算时间是不变的。
举一个简单的例子:不管n如何增长,都不会影响这个函数的计算时间,因此这个代码的时间复杂度都是O(1)。
const increament = n=>n++
O(n):
线性时间复杂度,随着数据规模n的增长,计算时间也会随着n线性增长。
典型的O(n)的例子就是线性查找。
const linearSeach = (arr, target) =>{
for (let i=0; i<arr.lenght; i++){
if(arr[i] === target){
return i
}
}
return -1;//返回-1表示没有查询到target在arr中
}
线性查找的时间消化与输入的数组数量n成一个线性比例,随着n规模的增大,时间也会线性增长。
O(logn):
对数时间复杂度,随着问题的规模n的增长,计算时间也会随着n对数级增长。
典型的例子就是二分查找法。
functions binarySearch(arr, target) {
let max = arr.length - 1
let min = 0
while (min <= max) {
let mid = Math.floor((max + min) / 2)
if (target < arr[mid]) { max = mid - 1 }
else if (target > arr[mid]) { min = mid + 1 }
else { return mid }
}
return -1
}
在二分查找法的代码中,通过while循环,成2倍数的缩减搜索范围,也就是说要经过log2^n次即可以跳出循环。
事实上在实际项目中,O(logn) 是一个非常好的时间复杂度,比如当 n = 100 的数据规模时,二分查找法只需要查找7次,线性查找需要100次,这对于计算机而言差距不大,但是当有10亿的数据规模的时候,二分查找依然只需要30次,而线性查找需要惊人的10亿次,O(logn) 时间复杂度的算法随着数据规模的增大,他的优势就越明显。
O(nlogn):
线性对数时间复杂度,随着数据规模n的增长,计算时间也会随着n呈现线性对数级增长。
这其中典型代表就是归并排序,我们会在对应⼩节详细分析它的复杂度。
待补充
O(n2)
平⽅级复杂度,典型情况是当存在双重循环的时候,即把 O(n) 的代码再嵌套循环⼀遍,它的时间复杂度就是 O(n²) 了.
代表应⽤是冒泡排序算法。
略