対数的ステップ数のフィボナッチ数列アルゴリズム
(define (fib n) (cond [(= n 0) 0] [(= n 1) 1] [else (+ (fib (- n 1)) (fib (- n 2)))]))
これを反復的になるように書き換えると以下のようになります。ステップ数はです。
(define (fib n) (fib-iter 1 0 n)) (define (fib-iter a b n) (if (= n 0) b (fib-iter (+ a b) a (- n 1))))
これをステップ数にするには、どうしたらよいでしょうか。この問題がSICPの問題1.19です。解説してみます。
上の反復的アルゴリズムでは、(fib n)は、(a, b)=(1, 0)に対して変換Tをn回掛けたものです。
さて、ここで、一般的な変換というものを考えてみましょう。
つまり
です。
行列で表現すると
となります。
よって、
となります。
したがって、
となります。
このことを利用すれば、対数的ステップ数のフィボナッチ数列アルゴリズムが以下のように書けます。
(define (fib n) (fib-iter 1 0 0 1 n)) (define (fib-iter a b p q n) (cond [(= n 0) b] [(even? n) (fib-iter a b (+ (* p p) (* q q)) ; p'を計算 (+ (* 2 p q) (* q q)) ; q'を計算 (/ n 2))] [else (fib-iter (+ (* b q) (* a q) (* a p)) (+ (* b p) (* a q)) p q (- n 1))]))