Number the H1 and H2 headings.

This commit is contained in:
Yudong Jin
2023-01-31 03:37:50 +08:00
parent dbbc1adc4f
commit eb0afc98ec
44 changed files with 263 additions and 257 deletions

View File

@ -2,9 +2,9 @@
comments: true
---
# 算法效率评估
# 2.1. 算法效率评估
## 算法评价维度
## 2.1.1. 算法评价维度
在开始学习算法之前,我们首先要想清楚算法的设计目标是什么,或者说,如何来评判算法的好与坏。整体上看,我们设计算法时追求两个层面的目标。
@ -18,7 +18,7 @@ comments: true
数据结构与算法追求“运行速度快、占用内存少”,而如何去评价算法效率则是非常重要的问题,因为只有知道如何评价算法,才能去做算法之间的对比分析,以及优化算法设计。
## 效率评估方法
## 2.1.2. 效率评估方法
### 实际测试
@ -36,7 +36,7 @@ comments: true
**复杂度分析克服了实际测试方法的弊端**。一是独立于测试环境,分析结果适用于所有运行平台。二是可以体现不同数据量下的算法效率,尤其是可以反映大数据量下的算法性能。
## 复杂度分析重要性
## 2.1.3. 复杂度分析重要性
复杂度分析给出一把评价算法效率的“标尺”,告诉我们执行某个算法需要多少时间和空间资源,也让我们可以开展不同算法之间的效率对比。

View File

@ -2,11 +2,11 @@
comments: true
---
# 空间复杂度
# 2.3. 空间复杂度
「空间复杂度 Space Complexity」统计 **算法使用内存空间随着数据量变大时的增长趋势**。这个概念与时间复杂度很类似。
## 算法相关空间
## 2.3.1. 算法相关空间
算法运行中,使用的内存空间主要有以下几种:
@ -202,7 +202,7 @@ comments: true
}
```
## 推算方法
## 2.3.2. 推算方法
空间复杂度的推算方法和时间复杂度总体类似,只是从统计“计算操作数量”变为统计“使用空间大小”。与时间复杂度不同的是,**我们一般只关注「最差空间复杂度」**。这是因为内存空间是一个硬性要求,我们必须保证在所有输入数据下都有足够的内存空间预留。
@ -452,7 +452,7 @@ comments: true
}
```
## 常见类型
## 2.3.3. 常见类型
设输入数据大小为 $n$ ,常见的空间复杂度类型有(从低到高排列)

View File

@ -2,7 +2,7 @@
comments: true
---
# 权衡时间与空间
# 2.4. 权衡时间与空间
理想情况下,我们希望算法的时间复杂度和空间复杂度都能够达到最优,而实际上,同时优化时间复杂度和空间复杂度是非常困难的。
@ -10,7 +10,7 @@ comments: true
大多数情况下,时间都是比空间更宝贵的,只要空间复杂度不要太离谱、能接受就行,**因此以空间换时间最为常用**。
## 示例题目 *
## 2.4.1. 示例题目 *
以 LeetCode 全站第一题 [两数之和](https://leetcode.cn/problems/two-sum/) 为例。

View File

@ -2,7 +2,7 @@
comments: true
---
# 小结
# 2.5. 小结
### 算法效率评估

View File

@ -2,9 +2,9 @@
comments: true
---
# 时间复杂度
# 2.2. 时间复杂度
## 统计算法运行时间
## 2.2.1. 统计算法运行时间
运行时间能够直观且准确地体现出算法的效率水平。如果我们想要 **准确预估一段代码的运行时间** ,该如何做呢?
@ -155,7 +155,7 @@ $$
但实际上, **统计算法的运行时间既不合理也不现实**。首先,我们不希望预估时间和运行平台绑定,毕竟算法需要跑在各式各样的平台之上。其次,我们很难获知每一种操作的运行时间,这为预估过程带来了极大的难度。
## 统计时间增长趋势
## 2.2.2. 统计时间增长趋势
「时间复杂度分析」采取了不同的做法,其统计的不是算法运行时间,而是 **算法运行时间随着数据量变大时的增长趋势** 。
@ -369,7 +369,7 @@ $$
**时间复杂度也存在一定的局限性**。比如,虽然算法 `A` 和 `C` 的时间复杂度相同,但是实际的运行时间有非常大的差别。再比如,虽然算法 `B` 比 `C` 的时间复杂度要更高,但在输入数据大小 $n$ 比较小时,算法 `B` 是要明显优于算法 `C` 的。对于以上情况,我们很难仅凭时间复杂度来判定算法效率高低。然而,即使存在这些问题,计算复杂度仍然是评判算法效率的最有效且常用的方法。
## 函数渐近上界
## 2.2.3. 函数渐近上界
设算法「计算操作数量」为 $T(n)$ ,其是一个关于输入数据大小 $n$ 的函数。例如,以下算法的操作数量为
@ -530,11 +530,11 @@ $T(n)$ 是个一次函数,说明时间增长趋势是线性的,因此易得
渐近上界的数学味儿有点重,如果你感觉没有完全理解,无需担心,因为在实际使用中我们只需要会推算即可,数学意义可以慢慢领悟。
## 推算方法
## 2.2.4. 推算方法
推算出 $f(n)$ 后,我们就得到时间复杂度 $O(f(n))$ 。那么,如何来确定渐近上界 $f(n)$ 呢?总体分为两步,首先「统计操作数量」,然后「判断渐近上界」。
### 1. 统计操作数量
### 1) 统计操作数量
对着代码,从上到下一行一行地计数即可。然而,**由于上述 $c \cdot f(n)$ 中的常数项 $c$ 可以取任意大小,因此操作数量 $T(n)$ 中的各种系数、常数项都可以被忽略**。根据此原则,可以总结出以下计数偷懒技巧:
@ -725,7 +725,7 @@ $$
}
```
### 2. 判断渐近上界
### 2) 判断渐近上界
**时间复杂度由多项式 $T(n)$ 中最高阶的项来决定**。这是因为在 $n$ 趋于无穷大时,最高阶的项将处于主导作用,其它项的影响都可以被忽略。
@ -743,7 +743,7 @@ $$
</div>
## 常见类型
## 2.2.5. 常见类型
设输入数据大小为 $n$ ,常见的时间复杂度类型有(从低到高排列)
@ -2309,7 +2309,7 @@ $$
<p align="center"> Fig. 阶乘阶的时间复杂度 </p>
## 最差、最佳、平均时间复杂度
## 2.2.6. 最差、最佳、平均时间复杂度
**某些算法的时间复杂度不是恒定的,而是与输入数据的分布有关**。举一个例子,输入一个长度为 $n$ 数组 `nums` ,其中 `nums` 由从 $1$ 至 $n$ 的数字组成,但元素顺序是随机打乱的;算法的任务是返回元素 $1$ 的索引。我们可以得出以下结论: