@@ -191,10 +191,10 @@ n! = n·(n − 1)!
191
191
192
192
使用` n ` 种硬币找零的方式为:
193
193
194
- 1 . 使用所有除了第一种之外的硬币为` a ` 找零的方式,加上
194
+ 1 . 使用所有除了第一种之外的硬币为` a ` 找零的方式,以及
195
195
2 . 使用` n ` 种硬币为更小的金额` a - d ` 找零的方式,其中` d ` 是第一种硬币的面额。
196
196
197
- 为了弄清楚为什么这是正确的,需要观察找零的方式数量可以分为两组,不使用人第一种硬币的方式, 和使用它们的方式。所以,用于找零方式总数等于不使用第一种硬币为该金额找零的方式数量 ,加上使用第一种硬币至少一次的方式数量。而后者的数量等于在使用第一种硬币之后,为剩余的金额找零的方式数量。
197
+ 为了弄清楚为什么这是正确的,可以看出,找零方式可以分为两组,不使用第一种硬币的方式, 和使用它们的方式。所以,找零方式的总数等于不使用第一种硬币为该金额找零的方式数量 ,加上使用第一种硬币至少一次的方式数量。而后者的数量等于在使用第一种硬币之后,为剩余的金额找零的方式数量。
198
198
199
199
因此,我们可以递归将给定金额的找零问题,归约为使用更少种类的硬币为更小的金额找零的问题。仔细考虑这个归约原则,并且说服自己,如果我们规定了下列基本条件,我们就可以使用它来描述算法:
200
200
@@ -217,15 +217,15 @@ n! = n·(n − 1)!
217
217
292
218
218
```
219
219
220
- ` count_change ` 函数生成属性递归过程 ,和` fib ` 的一个实现一样 ,它是重复的。它会花费很长时间来计算出` 292 ` 。 除非我们记忆这个函数。另一方面,设计迭代算法来计算出结果的方式并不是那么明显,我们将它留做一个挑战。
220
+ ` count_change ` 函数生成树形递归过程 ,和` fib ` 的首个实现一样 ,它是重复的。它会花费很长时间来计算出` 292 ` , 除非我们记忆这个函数。另一方面,设计迭代算法来计算出结果的方式并不是那么明显,我们将它留做一个挑战。
221
221
222
222
## 3.2.5 增长度
223
223
224
- 前面的例子表明,过程在花费的时间和空间计算资源上有显著差异。我们用于描述这个差异的便捷方式就是使用增长度的概念 ,来获得当输入变得更大时,过程所需资源的大致度量。
224
+ 前面的例子表明,不同过程在花费的时间和空间计算资源上有显著差异。我们用于描述这个差异的便捷方式,就是使用增长度的概念 ,来获得当输入变得更大时,过程所需资源的大致度量。
225
225
226
226
令` n ` 为度量问题规模的参数,` R(n) ` 为处理规模为` n ` 的问题的过程所需的资源总数。在我们前面的例子中,我们将` n ` 看做给定函数所要计算出的数值。但是还有其他可能。例如,如果我们的目标是计算某个数值的平方根近似值,我们会将` n ` 看做所需的有效位数的数量。通常,有一些问题相关的特性可用于分析给定的过程。与之相似,` R(n) ` 可用于度量所用的内存总数,所执行的基本的机器操作数量,以及其它。在一次只执行固定数量操作的计算中,用于求解表达式的所需时间,与求值过程中执行的基本机器操作数量成正比。
227
227
228
- 我们说,` R(n) ` 具有` Θ(f(n)) ` 的增长度,写作` R(n)=Θ(f(n)) ` (读作“theta ` f(n) ` ”),如果存在独立于` n ` 的常数` k1 ` 和` k2 ` ,那么对于任何的足够大的 ` n ` 值:
228
+ 我们说,` R(n) ` 具有` Θ(f(n)) ` 的增长度,写作` R(n)=Θ(f(n)) ` (读作“theta ` f(n) ` ”),如果存在独立于` n ` 的常数` k1 ` 和` k2 ` ,那么对于任何足够大的 ` n ` 值:
229
229
230
230
```
231
231
k1·f(n) <= R(n) <= k2·f(n)
@@ -236,24 +236,24 @@ k1·f(n) <= R(n) <= k2·f(n)
236
236
+ 下界` k1·f(n) ` ,以及
237
237
+ 上界` k2·f(n) ` 。
238
238
239
- 例如,计算` n! ` 所需的步骤数量与` n ` 成正比,所以这个过程所需步骤以 ` Θ(n) ` 增长。我们也看到了,` fact ` 递归实现` fact ` 的所需空间以` Θ(n) ` 增长。与之相反,迭代实现` fact_iter ` 花费相似的步骤数量,但是所需的空间保持不变。这里,我们说这个空间以` Θ(1) ` 成长 。
239
+ 例如,计算` n! ` 所需的步骤数量与` n ` 成正比,所以这个过程的所需步骤以 ` Θ(n) ` 增长。我们也看到了,递归实现` fact ` 的所需空间以` Θ(n) ` 增长。与之相反,迭代实现` fact_iter ` 花费相似的步骤数量,但是所需的空间保持不变。这里,我们说这个空间以` Θ(1) ` 增长 。
240
240
241
241
我们的树形递归的斐波那契数计算函数` fib ` 的步骤数量,随输入` n ` 指数增长。尤其是,我们可以发现,第 n 个斐波那契数是距离` φ^(n-2)/√5 ` 的最近整数,其中` φ ` 是黄金比例:
242
242
243
243
```
244
244
φ = (1 + √5)/2 ≈ 1.6180
245
245
```
246
246
247
- 我们也表示,步骤数量随返回值增长和整张 ,所以树形递归过程需要` Θ(φ^n) ` 的步骤,一个随 ` n ` 指数增长的函数。
247
+ 我们也表示,步骤数量随返回值增长而增长 ,所以树形递归过程需要` Θ(φ^n) ` 的步骤,它的一个随 ` n ` 指数增长的函数。
248
248
249
249
增长度只提供了过程行为的大致描述。例如,需要` n^2 ` 个步骤的过程和需要` 1000·n^2 ` 个步骤的过程,以及需要` 3·n^2+10·n+17 ` 个步骤的过程都拥有` Θ(n^2) ` 的增长度。在特定的情况下,增长度的分析过于粗略,不能在函数的两个可能实现中做出判断。
250
250
251
- 但是,增长度提供了实用的方法,来表示在改变问题规模的时候,我们应如何预期过程行为的改变。对于` Θ(n) ` (线性)的过程,使规模加倍只会使所需的资源总数加倍。对于指数的过程,每一点问题规模的增长都会使所用资源以固定因数翻倍。接下来的例子检测了一个增长度为对数的算法 ,所以使问题规模加倍,只会使所需资源以固定总数增加。
251
+ 但是,增长度提供了实用的方法,来表示在改变问题规模的时候,我们应如何预期过程行为的改变。对于` Θ(n) ` (线性)的过程,使规模加倍只会使所需的资源总数加倍。对于指数的过程,每一点问题规模的增长都会使所用资源以固定因数翻倍。接下来的例子展示了一个增长度为对数的算法 ,所以使问题规模加倍,只会使所需资源以固定总数增加。
252
252
253
253
## 3.2.6 示例:求幂
254
254
255
255
256
- 考虑计算给定数值的幂的问题 。我们希望有一个函数,它接受底数` b ` 和正整数指数` n ` 作为参数,并计算出` b^n ` 。一种方式就是通过递归定义:
256
+ 考虑对给定数值求幂的问题 。我们希望有一个函数,它接受底数` b ` 和正整数指数` n ` 作为参数,并计算出` b^n ` 。一种方式就是通过递归定义:
257
257
258
258
```
259
259
b^n = b·b^(n-1)
@@ -314,4 +314,4 @@ b^8 = b^4·b^4
314
314
1267650600228229401496703205376
315
315
```
316
316
317
- ` fast_exp ` 所生成的过程的空间和步骤数量随` n ` 以对数方式增长。为了弄清楚它,需要观察使用 ` fast_exp ` 计算` b^2n ` 比计算` b^n ` 只需要一步额外的乘法操作。于是,我们可计算的指数大小 ,在每次新的乘法操作时都会(近似)加倍。所以,计算` n ` 的指数所需乘法操作的数量,就像以 ` 2 ` 为底` n ` 那样慢 。这个过程拥有` Θ(log n) ` 的增长度。` Θ(log n) ` 和` Θ(n) ` 之间的差异在` n ` 非常大时变得显著。例如,` n ` 为` 1000 ` 时,` fast_exp ` 仅仅需要` 14 ` 个乘法操作,而不是` 1000 ` 。
317
+ ` fast_exp ` 所生成的过程的空间和步骤数量随` n ` 以对数方式增长。为了弄清楚它,可以看出,使用 ` fast_exp ` 计算` b^2n ` 比计算` b^n ` 只需要一步额外的乘法操作。于是,我们能够计算的指数大小 ,在每次新的乘法操作时都会(近似)加倍。所以,计算` n ` 的指数所需乘法操作的数量,增长得像以 ` 2 ` 为底` n ` 的对数那样慢 。这个过程拥有` Θ(log n) ` 的增长度。` Θ(log n) ` 和` Θ(n) ` 之间的差异在` n ` 非常大时变得显著。例如,` n ` 为` 1000 ` 时,` fast_exp ` 仅仅需要` 14 ` 个乘法操作,而不是` 1000 ` 。
0 commit comments