我试图理解我为一个练习阅读的解决方案,该练习定义了一个对数时间过程,用于查找斐波那契数列中的第 n 个数字。问题是计算机程序的结构和解释 (SICP) 中的 1.19。
剧透警报:这个问题的解决方案将在下面讨论。
Fib(n) 可以按如下线性时间计算:从 a = 1 和 b = 0 开始。Fib(n) 始终等于 b 的值。因此,最初,当 n = 0 时,Fib(0) = 0。每次应用以下变换时,n 都会增加 1,Fib(n) 等于 b 的值。
a <-- a + b
b <-- a
为了在对数时间内做到这一点,问题描述将变换 T 定义为变换
a' <-- bq + aq + ap
b' <-- bp + aq
其中 p = 0 和 q = 1,最初,因此此转换与上述转换相同。
然后应用上述变换两次,练习指导我们用 a 和 b 的原始值来表示新的值 a'' 和 b''。
a'' <-- b'q + a'q + a'p = (2pq + q^2)b + (2pq + q^2)a + (p^2 + q^2)a
b' <-- b'p + a'q = (p^2 + q^2)b + (2pq + q^2)a
然后,该练习将这种应用两次变换的应用称为“对变换求平方”。我的理解正确吗?
本练习的解决方案应用了使用上述平方变换值的技术来生成以对数时间运行的解决方案。问题如何在对数时间内运行?在我看来,每次我们使用平方变换的结果时,我们都需要进行一次变换而不是两次。那么我们如何连续每次将步数减半呢?
来自 schemewiki.org 的解决方案发布在下面:
(define (fib n)
(fib-iter 1 0 0 1 n))
(define (fib-iter a b p q count)
(cond ((= count 0) b)
((even? count)
(fib-iter a
b
(+ (square p) (square q))
(+ (* 2 p q) (square q))
(/ count 2)))
(else (fib-iter (+ (* b q) (* a q) (* a p))
(+ (* b p) (* a q))
p
q
(- count 1)))))
(define (square x) (* x x))