算法的复杂度分析
什么是算法复杂度?
不同的算法,其实效率是不一样的
让我举一个案例来比较两种不同的算法在查找数组中给定元素的时间复杂度
[1,2,3,4,5,6,7,...9999,n]
顺序查找
这种方法从头到尾遍历整个数组,依次比较每个元素和给定元素的值。
如果找到想等元素,则返回下标,如果遍历整个数组都找不到就返回-1。
function sequenSearch(array:number[],target:number) {let result = -1for (let i = 0;i<array.length;i++) {array[i] === target ? result = i : undefined}return result
}
最长时间复杂度:n
平均的时间复杂度: n / 2
该算法时间复杂度是O(n)
二分查找
这种算法假设数组是有序的,每次选择数组中间的元素与给定元素进行比较。
如果找到想等元素,则返回下,如果给定的元素比中间元素小,则在数组左半部分继续查找;如果给定的元素比中间元素大,则在数组右半部分继续查找。
这样每次查找都会将查找的范围减半,知道找到想等的元素或者查找范围为空。
function binarySearch(array: number[], target: number) {let left = 0;let right = array.length - 1;while (left <= right) {let mid = Math.floor((left + right) / 2);const midTarget = array[mid];if (midTarget === target) {return mid;} else if (midTarget < target) {left = mid + 1;} else {right = mid - 1;}}return -1;
}
最长时间复杂度:log(n,2)
平均的时间复杂度: log(n,2) / 2
该算法时间复杂度是O(log n)
大O表示法(Big O notation)
大O表示法(Big O notation)英文翻译为大O符号(维基百科翻译),中文通常翻译为大O表示法(标记法)。
- 这个记号则是在德国数论学家爱德蒙·兰道的著作中才推广的,因此它有时又称为兰道符号(Landau symbols)。
- 代表“order of …”.……阶)的大O,最初是一个大写希腊字母“O”(omicron),现今用的是大写拉丁字母“O”。
时间复杂度
分析算法时间效率举例
-
举个例子,解决一个规模为n的问题所花费的时间(或者所需步骤的数目)可以表示为:
T(n)=4n2-2n+2
-
当
n
增大时,n2
项开始占据主导地位,其他各项可以被忽略; -
举例说明:当
n=500
-
4n2
项是2n
项的1000
倍大,因此在大多数场合下,省略后者对表达式的值的影响将是可以忽略不计的。
进一步看,如果我们与任一其他级的表达式比较, n2的系数也是无关紧要的。
这样,针对第一个例子T(n) = 4n2- 2n+2
,大O符号就记下剩余的部分,写作:
T(n) ∈ o(n2)
或
T(n)= o(n2)
我们就说该例子算法具有**n2**
阶(平方阶)的时间复杂度,表示为**O(n2)**
常用函数阶
介绍
案例
图表
空间复杂度
空间复杂度指的是程序运行过程中所需要的额外存储空间。
空间复杂度也可以用大O表示法来表示;
空间复杂度的计算方法与时间复杂度类似,通常需要分析程序中需要额外分配的内存空间,如数组、变量、对象、递归调用等。
分析算法空间效率举例
举个栗子:
对于一个简单的递归算法来说,每次调用都会在内存中分配新的栈帧,这些栈帧占用了额外的空间。
-
因此,该算法的空间复杂度是o(n),其中n是递归深度。
而对于迭代算法来说,在每次迭代中不需要分配额外的空间,因此其空间复杂度为o(1)。
当空间复杂度很大时,可能会导致内存不足,程序崩溃。
在平时进行算法优化时,我们通常会进行如下的考虑: -
使用尽量少的空间(优化空间复杂度);
-
使用尽量少的时间(优化时间复杂度);
-
特定情况下:使用空间换时间或使用时间换空间;