Skip to content

算法分析

算法分析就是分析算法占用计算机资源(主要是占用 CPU 时间和内存空间)的多少。

时间复杂度

两种算法时间性能分析

通常有两种衡量算法时间性能的方法,即事后统计法和事前估算法。

事后统计法

事后统计法就是编写算法对于程序,统计其执行时间。但是一个算法用计算机语言实现后,在计算机上执行所消耗的时间与很多因素有关,如使用的语言、编译产生的机器语言代码质量等。

所以事后统计法拥有两个缺点,一是必须执行程序,二是存在很多因素掩盖了算法的本质。

事前估算法

事前估算法憋开这些与计算机硬件、软件有关的因素,仅考虑算法本身的效率高低,可以认为一个特定算法的“运行工作量”的大小只依赖于问题的规模。因此目前主要采用事前估算法来分析算法的时间性能。

时间复杂度分析

计算算法的频度 T(n)

一个算法是由控制结构(顺序、分支和循环)和原操作(指固有的数据类型的操作)构成。如下:

js
function fun(n) {
    let i;  //原操作
    let sum = 0;  //原操作
    for(i=0; i<n; i++) { // 这里也有 3 个原操作
        sum = sum + i //原操作
    }
    return i; //原操作
}

而算法的执行时间取决于控制结构原操作的综合效果。显然,在一个算法中执行原操作的次数越少,其执行的时间也就相对越少;执行原操作次数越多,其执行时间也就相对越多。也就是说,一个算法的执行时间可以由其中原操作的执行次数来计算。

假设算法的问题规模为 n。算法时间分析就是求出算法所有原操作的执行此时,它是问题规模 n 的函数,用 T(n)表示。

那么上述例子的 T(n) 为 1 + 1 + 1 + (n+1) + n + n + 1

js
function fun(n) {
    let i;  // 1
    let sum = 0;  // 1
    for(i=0; i<n; i++) { // 1 + (n+1) + n
        sum = sum + i // n
    }
    return i; // 1
}

T(n) 用 "O" 表示

由于算法分析不是绝对时间的比较,在求出 T(n) 后,通常进一步采用时间复杂度来表示。算法时间复杂度就是用 T(n) 的数量级来表示,记作 T(n) = O(f(n))。

T(n)变成 O 的规则:

  • 去掉常数
  • 去掉低阶
  • 去掉系数

所以上述例子的时间复杂度为 O(n)

常用的时间复杂度

O(1)(常数阶)、O(logn)(对数阶)、O(n)(线性阶)、O(nlogn)(线性对数阶)、O(n^2) (平方阶)、O(n^3)(立方阶)、O(2^n)(指数阶)

其从小到大的顺序关系如下: O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!)

空间复杂度

算法空间复杂度分析

一个算法的存储量包括输入数据所占的空间,程序本身所占的空间和临时变量所占的空间。这里在对算法进行存储空间分析只考察临时变量所占的空间。

js
function max(let arr[]) {
    let i, max = 0
    for(i=0;i<arr.length;i++) {
        if(arr[i] > arr[max])
        max = i
    }
    return arr[max]
}

就像上面的临时变量只有 i 和 max 为 1,所以空间复杂度就为 O(1)。

TIP

空间复杂度和时间复杂度一样都会去除常数、低阶和系数