再帰は、多くのアルゴリズムにおいて自然で直感的なアプローチを提供しますが、特に重複する計算を行う場合には非効率的です。メモ化は、計算結果を保存して再利用することで、再帰的なアルゴリズムのパフォーマンスを大幅に向上させるテクニックです。この教材では、再帰のメモ化を使用して、フィボナッチ数列の計算を最適化する方法を学びます。
メモ化は、関数の引数に対する戻り値をキャッシュすることで、同じ入力に対する計算を繰り返さないようにします。これにより、特に再帰的な関数において、計算時間が大幅に短縮されます。
フィボナッチ数列は、次のように定義されます: - F(0) = 0 - F(1) = 1 - F(n) = F(n-1) + F(n-2) (n >= 2)
この定義を用いると、フィボナッチ数列を計算する再帰関数を簡単に実装できます。
まず、メモ化を使わない再帰的なフィボナッチ数列の実装を見てみましょう。
def fibonacci(n):
if n <= 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n - 1) + fibonacci(n - 2)
# サンプル実行
print(fibonacci(10)) # 出力: 55
fibonacci
は、引数 n
に対してフィボナッチ数を計算します。n
が 0 または 1 の場合に直接結果を返します。fibonacci(n - 1)
と fibonacci(n - 2)
を呼び出します。この実装は分かりやすいですが、計算量は指数関数的であり、特に大きな n
に対しては非常に遅くなります。
次に、メモ化を使ってこの関数を最適化します。Pythonでは、functools
モジュールの lru_cache
デコレーターを使うことで、簡単にメモ化を実装できます。
from functools import lru_cache
@lru_cache(maxsize=None) # 無限キャッシュサイズ
def fibonacci_memo(n):
if n <= 0:
return 0
elif n == 1:
return 1
else:
return fibonacci_memo(n - 1) + fibonacci_memo(n - 2)
# サンプル実行
print(fibonacci_memo(10)) # 出力: 55
functools.lru_cache
デコレーターを使って、関数 fibonacci_memo
にメモ化機能を追加します。maxsize
パラメータで指定できますが、None
を設定することで無限にキャッシュを持つことができます。この変更により、計算量は線形時間に改善され、非常に大きな n
に対しても効率的にフィボナッチ数を計算できるようになります。
メモ化は、再帰的なアルゴリズムのパフォーマンスを劇的に向上させる強力な手法です。この教材では、フィボナッチ数列を例にして、メモ化の基本的な概念と実装方法を学びました。再帰を用いた問題に直面した場合は、ぜひメモ化を考慮してみてください。