通常用大O表示法表示算法的效率
如下图,从左到右,从上到下,效率依次递增

下面看几个算法题对应的时间空间复杂度
时间复杂度:O(1);空间复杂度:O(1)
时间的消耗和数组长度无关,无论数组多长,时间消耗都是固定的
php
function(array){
return array[0]
}
时间复杂度:O(log n);空间复杂度:O(1)
ini
// 二分法找数
const arr = [1,2,3,4,5,6,7];
const fn = (target)=>{
let start = 0,end=arr.length-1,middle,ele;
while(start<=end){
middle = Math.floor((start+end)/2);
ele = arr[middle];
if(ele === target){
console.log(middle);
return middle
} else if(target < ele){
end = middle-1
} else {
start = middle+1
}
}
}
fn(3)
-
每次查找都会把查找区间缩小一半(start/end/middle)。
-
所以查找次数最多为 log₂(n) 次(n 为数组长度)。
-
详细解释
- 第一次查找:n 个元素
- 第二次查找:n/2 个元素
- 第三次查找:n/4 个元素
- · · ·
- 直到只剩 1 个元素
所以总共查找次数为 log₂(n) 次,时间复杂度为 O(log n); 因为是循环实现,没有递归调用栈,空间复杂度为 O(1)
时间复杂度:O(n²); 空间复杂度:O(1)
ini
//选择排序
const arr = [1, 2, 19, 12, 21, 13, 8, 4];
const fn = (arr) => {
for (let i = 0; i < arr.length; i++) {
let min = i;
for (let j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
[arr[i], arr[min]] = [arr[min], arr[i]];
}
return arr;
};
const res = fn(arr);
-
外层循环遍历数组每个元素
i
。 -
内层循环从
i+1
开始,找出最小值索引min
。 -
将当前索引
i
和最小值位置min
的元素交换。 -
详细解释
- 时间复杂度
-
外层循环 :执行
n
次(n
是数组长度) -
里层循环
- 第一次内层循环:比较 n-1 次
- 第二次内层循环:比较 n-2 次
- · · ·
- 最后一次:比较 1 次
所以总共查找次数为(n-1)+(n-2)+(n-3)+...次,时间复杂度为 O(n²)。
-
- 空间复杂度
-
只使用了常数级额外空间(几个变量
i
,j
,min
)。所以空间复杂度为:O(1)
-
- 时间复杂度
时间复杂度:O(2ⁿ);空间复杂度O(n)
scss
//斐波拉契数列
function fn(num) {
if(num<=2) return 1;
return fn(num-1)+fn(num-2);
}

可以看到,每次调用都会分出两个子调用,形成一棵二叉树结构。
-
每层节点数量为 <math xmlns="http://www.w3.org/1998/Math/MathML"> 2 d 2^d </math>2d,其中
d
是深度。 -
总调用次数 ≈ <math xmlns="http://www.w3.org/1998/Math/MathML"> 2 n 2^n </math>2n
所以时间复杂度为O(2ⁿ)
递归的空间复杂度取决于最大递归调用栈的深度。