前端算法

83 阅读2分钟

1.算法的衡量标准

1.1 时间复杂度

时间复杂度指的是运行这段算法代码所需要的指令数量。 常用的时间复杂度按照量级划分一共有五种阶级:(这五个阶级应该烂熟于心)

1.常数阶级-O(1)

常数阶级指的是这段代码中的执行指令次数,不会随着某个变量改变,例如:

function o1(a,b){
    let temp = a;
    a = b;
    b = temp;
}

可以看出,这段代码里面是没有任何变量的,虽然这端代码执行起来需要指令次数可能各不相同,但是按照变量算的话,就是一个常量,不受变量影响,所以时间复杂度定义为O(1)。

2.线性阶级-O(n)

function sum (n) {
    int result = 0;
    for (let i = 0 ; i <= n ; i ++){
         result += i;
    }
    return result;
} 

3.平方阶级-O(n2)

平方阶O(n²) 就更容易理解了,如果把 O(n) 的代码再嵌套循环一遍,它的时间复杂度就是 O(n²) 了。

for(x=1; i<=n; x++) {
   for(i=1; i<=n; i++) {
       j = i;
       j++;
    }
}

而如果将一个n替换为m,那么时间复杂度就是O(m*n)

for(x=1; i<=m; x++) {
   for(i=1; i<=n; i++) {
       j = i;
       j++;
    }
}

4.对数阶级-O(logn)

如果前端的线性阶和平方阶可以通过记忆的话,那么对数阶是不太容易理解的地方。可以通过求循环次数来计算时间复杂度。

while(i<n) {
    i = i * 2
}

执行这段代码的指令次数假设为x,那么当x满足2的x次方 > n时候执行结束,反向求 x=log2^n。也就是说当这段代码执行了log2^n 次以后,循环代码结束了。因此这个代码的时间复杂度为:O(logn)

5.线性对数阶级-O(nlogn)

其实线性对数阶就是两层循环,只不过内层是对数阶,外层是线性阶。这样总的次数就是n*O(logN),例如

for(m=1; m<n; m++) {
    i = 1;
    while (i < n) {
        i = i * 2;
    }
}

1.2 空间复杂度

空间复杂度不是值程序自身占用的空间大小,而是程序执行过程中临时占用的空间大小。常用的三个阶级:擦韩国鸟叔O(1)、O(n)、O(n²)

1.常数阶级O(1)

    i = 1;
    j = 2;

2.线性阶级O(n)

    let arr = new Array(n);
    let j = 0;
    for (let i = 0; i<n; i++) {
        j = i+ j
    }

计算空间复杂度千万不要被循环所干扰,我们需要计算的是空间,循环可能会影响,但是不是绝对因素,需要具体分析当中所需要的空间大小。例如,第一行中需要n个空间单元放置数组,循环中只是从头到尾都只是对一个空间单元进行赋值操作,因此空间复杂度由第一行决定,为O(n)。 3.平方阶级O(n2)