フィボナッチ数列は、1から始まる前の結果に追加された数値の結果を合計するものです。
so.. 1 + 1 = 2
2 + 3 = 5
3 + 5 = 8
5 + 8 = 13
8 + 13 = 21
フィボナッチとは何かを理解したら、コードを分解し始めることができます。
public int fibonacci(int n) {
if(n == 0)
return 0;
else if(n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
最初のifステートメントは、ループが発生する可能性がある基本ケースをチェックします。その下のelse ifステートメントも同じことをしていますが、次のように書き直すことができます...
public int fibonacci(int n) {
if(n < 2)
return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
基本ケースが確立されたので、コールスタックを理解する必要があります。「fibonacci」への最初の呼び出しは、呼び出し元とは逆の順序で解決されるため、スタック(呼び出しのシーケンス)で最後に解決されます。最後に呼び出されたメソッドが最初に解決され、次に最後のメソッドがそのメソッドの前に呼び出されます。
したがって、すべての呼び出しは、これらの結果を使用して何かが「計算」される前に最初に行われます。入力が8の場合、出力は21になるはずです(上の表を参照)。
fibonacci(n-1)は、基本ケースに到達するまで呼び出され続け、その後、基本ケースに到達するまでfibonacci(n-2)が呼び出されます。スタックが逆の順序で結果を合計し始めると、結果は次のようになります...
1 + 1 = 1 ---- last call of the stack (hits a base case).
2 + 1 = 3 ---- Next level of the stack (resolving backwards).
2 + 3 = 5 ---- Next level of the stack (continuing to resolve).
それらは、正しい合計がスタックの最初の呼び出しに返されるまで、バブリング(逆方向に解決)を続け、そのようにして答えが得られます。
とは言っても、このアルゴリズムはコードが分割する各ブランチに対して同じ結果を計算するため、非常に非効率的です。はるかに優れたアプローチは、メモ化(キャッシュ)または再帰(ディープコールスタック)が不要な「ボトムアップ」アプローチです。
そのようです...
static int BottomUpFib(int current)
{
if (current < 2) return current;
int fib = 1;
int last = 1;
for (int i = 2; i < current; i++)
{
int temp = fib;
fib += last;
last = temp;
}
return fib;
}