学数据结构和算法的目的 => 实现程序的高速运行,那么必然要了解复杂度。
复杂度分为两个维度:时间、空间。在开发过程中,我们希望时间和内存消耗都越少越好,但很多时候无法做到兼顾,需要在时间和空间之间做出取舍已达到最佳状态。
对复杂度的计算一般采用事前分析估算的方法,即大O表示法。
接下来让我们进入复杂度的学习!
大O表示法——概念
由保罗·巴赫曼在《解析数论》中首先引入。它描述的是一个函数数量级的渐进上界,即算法最坏的情况。
某个算法的复杂度达到了这个问题复杂度的下界,即为最佳算法。
比如:从大小为100的存放数字的数组中找到10,我们需要从头到尾遍历,那么这个是时间复杂度就为 Ο(n),(这里n=100,下面讲解为何为Ο(n))。若10不是数组最后一项,我们在<100次的时候就找到 ,可跳出循环,所以,大O表示法描述的是最坏的情况。
说明:1. 决定算法复杂度的,是执行次数最多的语句;
2. 复杂度的得出,忽略了常量,低次幂和最高次幂的系数;
3. 加法法则:总复杂度量级最大的那段代码的时间复杂度;
3. 乘法法则:嵌套代码的复杂度等于内外代码复杂度的乘积。
大O表示法——四种时间复杂度
度量一个程序片段的执行时间
度量一个程序的执行时间通常有两种方法
事后统计的方法
事前分析估算的方法 => O
Ο(1)<Ο(log2(n))<Ο(n)<Ο(n^2)<Ο(n^3)<…<Ο(2^n)
我们可以用 console.time(''mark) console.timeEnd(''mark) 来查看执行时间
1. Ο(1):(常数阶)如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数;
let a = 1;
let b = 2;
let temp = a;
a = b;
b = temp;
2. Ο(log2(n)):(对数阶)当数据增大 n 倍时,耗时增大 logn 倍(这里的 log 是以 2 为底的,比如,当数据增大 256 倍时,耗时只增大 8 倍);
let i = 1;
while(i <= n) {
i *= 2;
}
3. Ο(n):(线性阶)数据量的增大几倍,耗时也增大几倍;
for(i = 1; i <= n; i++) {
...
}
4. Ο(n^2):(平方阶)数据量增大 n 倍时,耗时增大 n 的平方倍;
for(i = 1; i <= n; i++) {
for(j = 1; j <= n; j++) {
...
}
}
本文章持续完善中......