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)