メモ化再帰関数とは 再帰関数内で、同じ引数の再帰関数を複数回呼び出すような実装では、その計算結果を保持しておくことで、複数回呼び出さないような実装にしようというのがメモ化再帰関数です

フィボナッチ数列とはイタリアの数学者レオナルド=フィボナッチ(Leonardo Fibonacci)が名付けた数列です。

a[0] = 1, a[1] = 1
a[n + 2] = a[n] + a[n + 1]

(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, …)

このように前の2項を足してできあがる数列のことです。

普通の再帰でフィボナッチ数列を求める

以下のコードは普通の再帰でフィボナッチ数列の第n項を求めるものです。CalcFiboの引数が小さい場合はとくに問題はありませんが、1000程度の大きさの数になると待てど暮らせど処理が完了しません。

メモ化再帰でフィボナッチ数列を求める

上記のコードではCalcFiboを何度も呼び出しています。そこでメモ化再帰にします。ある引数が渡されたとき、その結果を保持しておくことで、また同じ引数で呼び出されたときすぐに値を返せるようにします。

これだと大きな引数(ただし戻り値がlong型の範囲内に収まる程度のもの)であっても短時間で処理を返すことができます。

スタックオーバーフローの例外が・・・

ただそれでも再帰を繰り返すとスタックオーバーフローの例外が発生します。20,000くらいの値を渡すと例外が発生します(このくらいの値を渡すと計算結果はlong型の範囲を大きく超えてしまうので処理そのものに意味が無いと言えば意味が無い)。

では再帰を用いなければどうなるのでしょうか?

Calcメソッドが複数回呼び出された場合、最初から計算をしなくていいように計算結果とどこまで計算したかをフィールド変数に保存しています。