遞歸實作費波納契數列雖然程式碼極度簡潔,完美對應數學定義,但其指數級時間複雜度使其在實務應用中極受限制。本文深入剖析遞歸解法的運作機制、效能瓶頸與改良方向。
#include <stdio.h>
int fibonacci(int num);
int main() {
int num, result;
printf("請輸入項數: ");
scanf("%d", &num);
result = fibonacci(num);
printf("第 %d 項結果: %d\n", num, result);
return 0;
}
int fibonacci(int num) {
if (num == 1 || num == 2)
return 1;
return fibonacci(num - 1) + fibonacci(num - 2);
}
以 fibonacci(5) 為例,呼叫樹呈現二元樹結構:
fib(5)
├── fib(4)
│ ├── fib(3)
│ │ ├── fib(2) → 1
│ │ └── fib(1) → 1
│ └── fib(2) → 1
└── fib(3)
├── fib(2) → 1
└── fib(1) → 1
總共產生 9 次函數呼叫,其中 fib(3)、fib(2)、fib(1) 重複計算多次。
引入陣列快取已計算結果,將時間複雜度降至 O(n):
#include <stdio.h>
#define MAX 100
long long memo[MAX];
long long fib_memo(int n) {
if (n <= 2) return 1;
if (memo[n] != 0) return memo[n];
return memo[n] = fib_memo(n-1) + fib_memo(n-2);
}
| 維度 | 遞歸 | 迭代 | 記憶化遞歸 |
|---|---|---|---|
| 程式碼簡潔度 | ★★★★★ | ★★★☆☆ | ★★★★☆ |
| 時間效能 | ★☆☆☆☆ | ★★★★★ | ★★★★★ |
| 空間效能 | ★★☆☆☆ | ★★★★★ | ★★★☆☆ |
| 適合場景 | 教學、小 n | 生產環境 | 需遞歸邏輯時 |
遞歸版費波納契是理解遞歸機制的優良教材,但生產環境務必避免直接使用朴素遞歸。掌握從遞歸到迭代、記憶化、動態規劃的演進路徑,是演算法優化的核心能力之一。