通常用大O表示法表示算法的效率
如下图,从左到右,从上到下,效率依次递增
下面看几个算法题对应的时间空间复杂度
-
时间复杂度:O(1);空间复杂度:O(1)
时间的消耗和数组长度无关,无论数组多长,时间消耗都是固定的
function(array){ return array[0] } -
时间复杂度:O(log n);空间复杂度:O(1)
// 二分法找数 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)
//选择排序 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)
//斐波拉契数列 function fn(num) { if(num<=2) return 1; return fn(num-1)+fn(num-2); }
可以看到,每次调用都会分出两个子调用,形成一棵二叉树结构。
-
每层节点数量为 ,其中
d是深度。 -
总调用次数 ≈
所以时间复杂度为O(2ⁿ)
递归的空间复杂度取决于最大递归调用栈的深度。