これは JavaScript のせいではなく、アルゴリズムの問題です。同じサブ問題を何度も再計算していますが、N が大きくなるとさらに悪化します。これは、単一の呼び出しの呼び出しグラフです。
F(32)
/ \
F(31) F(30)
/ \ / \
F(30) F(29) F(29) F(28)
/ \ / \ / \ | \
F(29) F(28) F(28) F(27) F(28) F(27) F(27) F(26)
... deeper and deeper
このツリーからわかるように、いくつかのフィボナッチ数を数回計算しています。たとえば、F(28) は 4 回計算されています。「アルゴリズム設計マニュアル」本から:
このアルゴリズムが F(n) を計算するのにかかる時間は? F(n+1) /F(n) ≈ φ = (1 + sqrt(5))/2 ≈ 1.61803 なので、これは F(n) > 1.6^n を意味します。再帰ツリーには葉として 0 と 1 しかないため、これほど多くの数を合計すると、少なくとも 1.6^n の葉またはプロシージャ コールが必要になります。この控えめな小さなプログラムの実行には指数関数的な時間がかかります!
メモ化を使用するか、ソリューションをボトムアップで構築する必要があります (つまり、最初に小さなサブ問題)。
このソリューションはメモ化を使用します (したがって、各フィボナッチ数を 1 回だけ計算します)。
var cache = {};
function fib(n) {
if (!cache[n]) {
cache[n] = (n < 2) ? n : fib(n - 1) + fib(n - 2);
}
return cache[n];
}
これはそれをボトムアップで解決します:
function fib(n) {
if (n < 2) return n;
var a = 0, b = 1;
while (--n) {
var t = a + b;
a = b;
b = t;
}
return b;
}