什么是算法:算法是解决一系列特定问题的执行步骤
如何判定算法好坏:
事后统计法
如果单从执行效率上评估,我们会想到比较对同一组数据处理时间,这种方法叫做事后统计法,这种方案有比较明显的缺点:
- 执行时间依赖于硬件以及运行时等不确定因素影响
- 必须编写对应的测试代码
- 测试数据难保证公正性
大O表示法
一般从以下维度评估算法优劣
- 确定性、可读性、健壮性(对不合理输入的反应和处理能力)
- 时间复杂度(time comflexity):估算程序指令执行次数(执行时间)
- 空间复杂度(space comflexity):估算所需占用的存储空间
为了描述算法复杂度,使用“O”表示,O表示数据规模n对应的复杂度
使用数字即可表示复杂度,就记为O(1)
- 9->O(1)
使用n表示复杂度,记为O(n) - 2n+3 -> O(n)
使用表示复杂度,记为O() - ->O() 以次类推,可以写成O(),O()等等
常见的复杂度
| 执行次数 | 复杂度 | 非正式术语 |
|---|---|---|
| 9 | O(1) | 常数阶 |
| 2n+3 | O(n) | 线性阶 |
| O(logn) | 对数阶 | |
| O() | 平方阶 | |
| O(nlogn) | nlogn阶 | |
| O() | 立方阶 | |
| O() | 指数阶 |
常用复杂度排序: O(1) < O(logn) < O(n) < O(nlogn) < O() < O() < O() < O(n!) < O()
注意:大O表示法仅仅是一个粗略的分析模型,是一种估算,在短时间内分析出算法执行效率
后续还会穿插介绍算法评价的其他角度:
- 最好最坏复杂度
- 均摊复杂度
- 复杂度震荡
- 平均复杂度
借助函数生成工具计算算法复杂度:zh.numberempire.com/graphingcal…
算法复杂度案例
O(1)
for (int i = 0; i < 4; i++) {
System.out.println("test");
}
O(n)
for (int i = 0; i < n; i++) {
System.out.println("test");
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < 15; j++) {
System.out.println("test");
}
}
O()
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
System.out.println("test");
}
}
O(logn)
// 执行次数 = log2(n)
// O(logn)
while ((n = n / 2) > 0) {
System.out.println(n);
}
O(nlogn)
执行次数 = log2(n)*n
for (int i = 1; i < n; i = i * 2) {
for (int j = 0; j < n; j++) {
System.out.println("test");
}
}