遞歸代碼優雅簡潔,但對於斐波那契數列這類重疊子問題,遞歸會導致指數級調用爆炸,嚴重拖垮性能甚至癱瘓系統。本文通過實測對比遞歸與迭代實現,直觀展示效率差距,並給出工程選型建議。
// 遞歸實現
public static long fibRecursive(int n) {
if (n <= 2) return 1;
return fibRecursive(n-1) + fibRecursive(n-2);
}
// 迭代實現
public static long fibIterative(int n) {
if (n <= 2) return 1;
long a = 1, b = 1, c = 0;
for (int i = 3; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}
| 指標 | 遞歸 | 迭代 |
|---|---|---|
| F(40) 耗時 | 明顯卡頓(秒級) | 瞬間完成(毫秒級) |
| CPU 佔用 | 飆升至 100%,系統假死 | 極低,無感知 |
| 記憶體壓力 | 棧幀疊加,易 StackOverflow | O(1) 常數空間 |
| n=100 可行性 | 不可行(棧溢出/超時) | 輕鬆應對(需 BigInteger) |
遞歸樹中大量重複子問題:F(n) 調用 F(n-1) 和 F(n-2),而 F(n-1) 又調用 F(n-2) 和 F(n-3)... 總調用次數約 O(1.618^n)(黃金比例指數)。
自底向上,僅保留前兩項,時間 O(n),空間 O(1),無重複計算,無棧溢出風險。
O(n),但仍需 O(n) 棧空間。O(log n),屬於算法進階範疇。-Xss 增大棧,或改寫為顯式棧模擬遞歸。遞歸是思維工具,迭代是工程工具。能不用遞歸,就不用遞歸——這不是保守,是對系統穩定性的敬畏。
下次面試遇到「斐波那契怎麼實現」,請自信寫出迭代版,並補充:「遞歸版僅供教學演示,生產環境堅決不用」。