算法基础,了解算法的基础知识,算法的种类,知道什么是好算法。
算法基础种类分别有: 1 、 n 、 n*n 。
一般使用公式或瀑布式条件判断的算法策略属于 1 ;使用单个循环的属于 n ;使用嵌套循环的属于 n*n 。3 种算法中往往常数算法 1 要优于 n 和 n*n 。给以下基础操作次数公式分类:
1 : 3 、 5 、 9 等n : n 、 n+1 、 2n+3 等n*n : n^2 、 n^2+5 、 2n^3+1 等一般判断算法好坏,更应该关注函数公式的主项:指数最高项。
比如算法 2n^2+n+3 对比算法 n^3+2n+1 ,因为 2n^2 指数低于 n^3 ,所以算法 2n^2+n+3 优于算法 n^3+2n+1 。
以下算法一,算法策略使用 循环 ,编译后的代码质量为 n 次,问题的输入规模 100 ,机器执行指令的速度取决于算法运行所在计算机。
let sum = 0, i = 1, n = 100;
for (; i <= n; i++) {
sum += i; // 执行 n 次
}
以下算法二,算法策略使用 公式 ,编译后的代码质量为 1 次,问题的输入规模 100 ,机器执行指令的速度取决于算法运行所在计算机。
let sum = 0, i = 1, n = 100;
sum = (i + n) * n / 2; // 执行 1 次
对比以上算法,它们的输入规模都是 100 ,在同一计算机运行的情况下,算法一的基础操作次数受输入规模的影响,造成工作量超出算法二,所以算法二效率更高。
以下表格遍历例子,算法策略使用 嵌套的循环 ,编译后的代码质量为 n^2 次,问题的输入规模 3x3 ,机器执行指令的速度取决于算法运行所在计算机。
let sum = 0,
table = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
for (let i = 0; i <= table.length; i++) {
for (let j = 0; j <= table[i].length; j++) {
sum += table[i][j]; // 执行 n^2 次
}
}
以上算法,它根据表格的大小,基础操作的数量是以指数上升的,所以 3x3 的表格内数值总和计算一共有基础操作 3^2 等于 9 次。
复杂度分为:时间复杂度或空间复杂度 一般计算 “复杂度” 是指 “时间复杂度”,而不是空间复杂度,目前主流还是时间复杂度,不求用内存换取时间。
T(n) = O(f(n)), f(n) 为算法的函数或入口,随着输入规模 n 的增长, T(n) 增长最慢的算法为最优算法。因为以下原因:
基础操作数量 = 时间
所以当 n 翻倍时,基础操作数量增长越少,花费的时间越少。
上面用到的三个求和算法例子,如果用大 O 表示算法的时间复杂度分别为 O(1) 、 O(n) 、 O(n^2) 。
大 O 记法表示时间的增长率
O(1) :增长率不变O(n) :增长率倍数增长O(n^2) :增长率指数增长用一下方法来推导 5 、 2n+3 、 n(n+1)/2 和 O(logn) 的大 O 阶:
5 => O(1) ,
2n+3 => O(n) ,
n(n+1)/2 => O(n^2)
一面这个例子的话就是 O(logn) :
let i = 1, n = 100;
while (i < n) {
i *= 2; // 2^x = n,那么 x = log(2)n,x 为循环次数
}
| 例子 | 时间复杂度 | 术语 |
|---|---|---|
| 5 | O(1) | 常数阶 |
| 3n+4 | O(n) | 线性阶 |
| 3n^2+4n+5 | O(n^2) | 平方阶 |
| 3log(2)n+4 | O(logn) | 对数阶 |
| 2n+3nlog(2)n+14 | O(nlogn) | nlogn 阶 |
| n^3+2n^2+4n+6 | O(n^3) | 立方阶 |
| 2^n | O(2^n) | 指数阶 |
时间复杂度对比:
O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)