This commit is contained in:
krahets
2023-08-19 22:07:27 +08:00
parent 71c7786f51
commit 2e27ad1680
99 changed files with 283 additions and 283 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ comments: true
icon: material/timer-sand
---
# 2.   复杂度
# 第 2 章   复杂度
<div class="center-table" markdown>
@@ -2,7 +2,7 @@
comments: true
---
# 2.1. &nbsp; 算法效率评估
# 2.1 &nbsp; 算法效率评估
在算法设计中,我们先后追求以下两个层面的目标:
@@ -18,7 +18,7 @@ comments: true
效率评估方法主要分为两种:实际测试和理论估算。
## 2.1.1. &nbsp; 实际测试
## 2.1.1 &nbsp; 实际测试
假设我们现在有算法 `A` 和算法 `B` ,它们都能解决同一问题,现在需要对比这两个算法的效率。最直接的方法是找一台计算机,运行这两个算法,并监控记录它们的运行时间和内存占用情况。这种评估方式能够反映真实情况,但也存在较大局限性。
@@ -26,7 +26,7 @@ comments: true
**展开完整测试非常耗费资源**。随着输入数据量的变化,算法会表现出不同的效率。例如,在输入数据量较小时,算法 `A` 的运行时间比算法 `B` 更少;而输入数据量较大时,测试结果可能恰恰相反。因此,为了得到有说服力的结论,我们需要测试各种规模的输入数据,而这样需要耗费大量的计算资源。
## 2.1.2. &nbsp; 理论估算
## 2.1.2 &nbsp; 理论估算
由于实际测试具有较大的局限性,我们可以考虑仅通过一些计算来评估算法的效率。这种估算方法被称为「渐近复杂度分析 Asymptotic Complexity Analysis」,简称为「复杂度分析」。
@@ -40,7 +40,7 @@ comments: true
如果你对复杂度分析的概念仍感到困惑,无需担心,我们会在后续章节详细介绍。
## 2.1.3. &nbsp; 复杂度的重要性
## 2.1.3 &nbsp; 复杂度的重要性
复杂度分析为我们提供了一把评估算法效率的“标尺”,帮助我们衡量了执行某个算法所需的时间和空间资源,并使我们能够对比不同算法之间的效率。
@@ -2,11 +2,11 @@
comments: true
---
# 2.3. &nbsp; 空间复杂度
# 2.3 &nbsp; 空间复杂度
「空间复杂度 Space Complexity」用于衡量算法占用内存空间随着数据量变大时的增长趋势。这个概念与时间复杂度非常类似,只需将“运行时间”替换为“占用内存空间”。
## 2.3.1. &nbsp; 算法相关空间
## 2.3.1 &nbsp; 算法相关空间
算法运行过程中使用的内存空间主要包括以下几种:
@@ -292,7 +292,7 @@ comments: true
```
## 2.3.2. &nbsp; 推算方法
## 2.3.2 &nbsp; 推算方法
空间复杂度的推算方法与时间复杂度大致相同,只需将统计对象从“计算操作数量”转为“使用空间大小”。
@@ -656,7 +656,7 @@ comments: true
```
## 2.3.3. &nbsp; 常见类型
## 2.3.3 &nbsp; 常见类型
设输入数据大小为 $n$ ,常见的空间复杂度类型有(从低到高排列):
@@ -1978,7 +1978,7 @@ $$
再例如“数字转化为字符串”,输入任意正整数 $n$ ,它的位数为 $\log_{10} n$ ,即对应字符串长度为 $\log_{10} n$ ,因此空间复杂度为 $O(\log_{10} n) = O(\log n)$ 。
## 2.3.4. &nbsp; 权衡时间与空间
## 2.3.4 &nbsp; 权衡时间与空间
理想情况下,我们希望算法的时间复杂度和空间复杂度都能达到最优。然而在实际情况中,同时优化时间复杂度和空间复杂度通常是非常困难的。
+2 -2
View File
@@ -2,7 +2,7 @@
comments: true
---
# 2.4. &nbsp; 小结
# 2.4 &nbsp; 小结
**算法效率评估**
@@ -26,7 +26,7 @@ comments: true
- 我们通常只关注最差空间复杂度,即统计算法在最差输入数据和最差运行时间点下的空间复杂度。
- 常见空间复杂度从小到大排列有 $O(1)$ , $O(\log n)$ , $O(n)$ , $O(n^2)$ , $O(2^n)$ 等。
## 2.4.1. &nbsp; Q & A
## 2.4.1 &nbsp; Q & A
!!! question "尾递归的空间复杂度是 $O(1)$ 吗?"
@@ -2,7 +2,7 @@
comments: true
---
# 2.2. &nbsp; 时间复杂度
# 2.2 &nbsp; 时间复杂度
运行时间可以直观且准确地反映算法的效率。如果我们想要准确预估一段代码的运行时间,应该如何操作呢?
@@ -187,7 +187,7 @@ $$
但实际上,**统计算法的运行时间既不合理也不现实**。首先,我们不希望预估时间和运行平台绑定,因为算法需要在各种不同的平台上运行。其次,我们很难获知每种操作的运行时间,这给预估过程带来了极大的难度。
## 2.2.1. &nbsp; 统计时间增长趋势
## 2.2.1 &nbsp; 统计时间增长趋势
「时间复杂度分析」采取了一种不同的方法,其统计的不是算法运行时间,**而是算法运行时间随着数据量变大时的增长趋势**。
@@ -446,7 +446,7 @@ $$
**时间复杂度也存在一定的局限性**。例如,尽管算法 `A` 和 `C` 的时间复杂度相同,但实际运行时间差别很大。同样,尽管算法 `B` 的时间复杂度比 `C` 高,但在输入数据大小 $n$ 较小时,算法 `B` 明显优于算法 `C` 。在这些情况下,我们很难仅凭时间复杂度判断算法效率高低。当然,尽管存在上述问题,复杂度分析仍然是评判算法效率最有效且常用的方法。
## 2.2.2. &nbsp; 函数渐近上界
## 2.2.2 &nbsp; 函数渐近上界
给定一个函数 `algorithm()`
@@ -638,7 +638,7 @@ $T(n)$ 是一次函数,说明时间的增长趋势是线性的,因此其时
也就是说,计算渐近上界就是寻找一个函数 $f(n)$ ,使得当 $n$ 趋向于无穷大时,$T(n)$ 和 $f(n)$ 处于相同的增长级别,仅相差一个常数项 $c$ 的倍数。
## 2.2.3. &nbsp; 推算方法
## 2.2.3 &nbsp; 推算方法
渐近上界的数学味儿有点重,如果你感觉没有完全理解,也无需担心。因为在实际使用中,我们只需要掌握推算方法,数学意义可以逐渐领悟。
@@ -894,7 +894,7 @@ $$
</div>
## 2.2.4. &nbsp; 常见类型
## 2.2.4 &nbsp; 常见类型
设输入数据大小为 $n$ ,常见的时间复杂度类型包括(按照从低到高的顺序排列):
@@ -2952,7 +2952,7 @@ $$
请注意,因为 $n! > 2^n$ ,所以阶乘阶比指数阶增长地更快,在 $n$ 较大时也是不可接受的。
## 2.2.5. &nbsp; 最差、最佳、平均时间复杂度
## 2.2.5 &nbsp; 最差、最佳、平均时间复杂度
**算法的时间效率往往不是固定的,而是与输入数据的分布有关**。假设输入一个长度为 $n$ 的数组 `nums` ,其中 `nums` 由从 $1$ 至 $n$ 的数字组成,但元素顺序是随机打乱的,任务目标是返回元素 $1$ 的索引。我们可以得出以下结论: