Skip to content

Commit 8c8b625

Browse files
committed
Update 01.01.02-Algorithm-Complexity.md
1 parent 4cce089 commit 8c8b625

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

docs/ch01/01.01/01.01.02-Algorithm-Complexity.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ def algorithm(n):
5151
return fact
5252
```
5353

54-
把上述算法中所有语句的执行次数加起来 $1 + n + n + 1 = 2n + 2$,可以用一个函数 $f(n)$ 来表达语句的执行次数:$f(n) = 2n + 2$。
54+
把上述算法中所有语句的执行次数加起来 $1 + n + n + 1 = 2 \times n + 2$,可以用一个函数 $f(n)$ 来表达语句的执行次数:$f(n) = 2 \times n + 2$。
5555

56-
则时间复杂度的函数可以表示为:$T(n) = O(f(n))$。它表示的是随着问题规模 n 的增大,算法执行时间的增长趋势跟 $f(n)$ 相同。$O$ 是一种渐进符号,$T(n)$ 称作算法的 **渐进时间复杂度(Asymptotic Time Complexity)**,简称为 **时间复杂度**
56+
则时间复杂度的函数可以表示为:$T(n) = O(f(n))$。它表示的是随着问题规模 $n$ 的增大,算法执行时间的增长趋势跟 $f(n)$ 相同。$O$ 是一种渐进符号,$T(n)$ 称作算法的 **渐进时间复杂度(Asymptotic Time Complexity)**,简称为 **时间复杂度**
5757

5858
所谓「算法执行时间的增长趋势」是一个模糊的概念,通常我们要借助像上边公式中 $O$ 这样的「渐进符号」来表示时间复杂度。
5959

@@ -69,7 +69,7 @@ def algorithm(n):
6969
7070
也就是说,如果函数 $f(n) = \Theta(g(n))$,那么我们能找到两个正数 $c_1$、$c_2$,使得 $f(n)$ 被 $c_1 \cdot g(n)$ 和 $c_2 \cdot g(n)$ 夹在中间。
7171

72-
例如:$T(n) = 3n^2 + 4n + 5 = \Theta(n^2)$,可以找到 $c_1 = 1$,$c_2 = 12$,$n_0 = 1$,使得对于所有 $n \ge 1$,都有 $n^2 \le 3n^2 + 4n + 5 \le 12n^2$。
72+
例如:$T(n) = 3 \times n^2 + 4 \times n + 5 = \Theta(n^2)$,可以找到 $c_1 = 1$,$c_2 = 12$,$n_0 = 1$,使得对于所有 $n \ge 1$,都有 $n^2 \le 3 \times n^2 + 4 \times n + 5 \le 12 \times n^2$。
7373

7474
#### 2.2.2 $O$ 渐进上界符号
7575

@@ -173,7 +173,7 @@ def permutations(arr, start, end):
173173
arr[i], arr[start] = arr[start], arr[i]
174174
```
175175

176-
上述代码中实现「全排列」使用了递归的方法。假设数组 $arr$ 长度为 $n$,第一层 `for` 循环执行了 $n$ 次,第二层 `for` 循环执行了 $n - 1$ 次。以此类推,最后一层 `for` 循环执行了 $1$ 次,将所有层 `for` 循环的执行次数累乘起来为 $n \times (n - 1) \times (n - 2) \times … \times 2 \times 1 = n!$ 次。则整个算法的 `for` 循环中基本语句的执行次数为 $n!$ 次,所以对应时间复杂度为 $O(n!)$。
176+
上述代码中实现「全排列」使用了递归的方法。假设数组 $arr$ 长度为 $n$,第一层 for 循环执行了 $n$ 次,第二层 for 循环执行了 $n - 1$ 次。以此类推,最后一层 for 循环执行了 $1$ 次,将所有层 for 循环的执行次数累乘起来为 $n \times (n - 1) \times (n - 2) \times … \times 2 \times 1 = n!$ 次。则整个算法的 for 循环中基本语句的执行次数为 $n!$ 次,所以对应时间复杂度为 $O(n!)$。
177177

178178
#### 2.3.5 对数 $O(\log n)$
179179

@@ -187,7 +187,7 @@ def algorithm(n):
187187
return cnt
188188
```
189189

190-
上述代码中 `cnt = 1` 的时间复杂度为 $O(1)$ 可以忽略不算。`while` 循环体中 $cnt$ 从 $1$ 开始,每循环一次都乘以 $2$。当大于等于 $n$ 时循环结束。变量 $cnt$ 的取值是一个等比数列:$2^02^12^2,…,2^x$,根据 $2^x = n$,可以得出这段循环体的执行次数为 $\log_2n$,所以这段代码的时间复杂度为 $O(\log_2n)$。
190+
上述代码中 `cnt = 1` 的时间复杂度为 $O(1)$ 可以忽略不算。while 循环体中 $cnt$ 从 $1$ 开始,每循环一次都乘以 $2$。当大于等于 $n$ 时循环结束。变量 $cnt$ 的取值是一个等比数列:$2^0, 2^1, 2^2, …, 2^x$,根据 $2^x = n$,可以得出这段循环体的执行次数为 $\log_2n$,所以这段代码的时间复杂度为 $O(\log_2n)$。
191191

192192
因为 $\log n = k \times \log_2 n$,这里 $k = 3.322$,所以,$\log n$ 与 $\log_2 n$ 的差别比较小。为了方便书写,通常我们将对数时间复杂度写作是 $O(\log n)$。
193193

@@ -232,15 +232,15 @@ def find(nums, val):
232232
return pos
233233
```
234234

235-
这段代码要实现的功能是:从一个整数数组 $nums$ 中查找值为 $val$ 的变量出现的位置。如果不考虑 `break` 语句,根据「2.3 时间复杂度计算」中讲的分析步骤,这个算法的时间复杂度是 $O(n)$,其中 $n$ 代表数组的长度。
235+
这段代码要实现的功能是:从一个整数数组 $nums$ 中查找值为 $val$ 的变量出现的位置。如果不考虑 break 语句,根据「2.3 时间复杂度计算」中讲的分析步骤,这个算法的时间复杂度是 $O(n)$,其中 $n$ 代表数组的长度。
236236

237-
但是如果考虑 `break` 语句,那么就需要考虑输入的内容了。如果数组中第 $1$ 个元素值就是 $val$,那么剩下 $n - 1$ 个数据都不要遍历了,那么时间复杂度就是 $O(1)$,即最佳时间复杂度为 $O(1)$。如果数组中不存在值为 $val$ 的变量,那么就需要把整个数组遍历一遍,时间复杂度就变成了 $O(n)$,即最差时间复杂度为 $O(n)$。
237+
但是如果考虑 break 语句,那么就需要考虑输入的内容了。如果数组中第 $1$ 个元素值就是 $val$,那么剩下 $n - 1$ 个数据都不要遍历了,那么时间复杂度就是 $O(1)$,即最佳时间复杂度为 $O(1)$。如果数组中不存在值为 $val$ 的变量,那么就需要把整个数组遍历一遍,时间复杂度就变成了 $O(n)$,即最差时间复杂度为 $O(n)$。
238238

239239
这样下来,时间复杂度就不唯一了。怎么办?
240240

241241
我们都知道,最佳时间复杂度和最坏时间复杂度都是极端条件下的时间复杂度,发生的概率其实很小。为了能更好的表示正常情况下的复杂度,所以我们一般采用平均时间复杂度作为时间复杂度的计算方式。
242242

243-
还是刚才的例子,在数组 $nums$ 中查找变量值为 $val$ 的位置,总共有 $n + 1$ 种情况:「在数组的的 $0 \sim n - 1$ 个位置上」和「不在数组中」。我们将所有情况下,需要执行的语句次数累加起来,再除以 $n + 1$,就可以得到平均需要执行的语句次数,即:$\frac{1 + 2 + 3 + ... + n + n}{n + 1} = \frac{n(n + 3)}{2(n + 1)}$。将公式简化后,得到的平均时间复杂度就是 $O(n)$。
243+
还是刚才的例子,在数组 $nums$ 中查找变量值为 $val$ 的位置,总共有 $n + 1$ 种情况:「在数组的的 $0 \sim n - 1$ 个位置上」和「不在数组中」。我们将所有情况下,需要执行的语句次数累加起来,再除以 $n + 1$,就可以得到平均需要执行的语句次数,即:$\frac{1 + 2 + 3 + ... + n + n}{n + 1} = \frac{n \times (n + 3)}{2 \times (n + 1)}$。将公式简化后,得到的平均时间复杂度就是 $O(n)$。
244244

245245
通常只有同一个算法在输入内容不同,不同时间复杂度有量级的差距时,我们才会通过三种时间复杂度表示法来区分。一般情况下,使用其中一种就可以满足需求了。
246246

0 commit comments

Comments
 (0)