迴圈效能優於遞迴 (Java 無尾呼叫優化)。遞迴每層呼叫消耗堆疊幀,大量資料易導致 StackOverflowError。
// 遞迴階乘
long factRec(int n) { return n <= 1 ? 1 : n * factRec(n - 1); }
// 迴圈階乘
long factIter(int n) { long r = 1; for (int i = 2; i <= n; i++) r *= i; return r; }
n = 100,000:遞迴 → StackOverflowError;迴圈 → 瞬間完成 (結果溢位但不崩潰)。n = 10,000:遞迴約 2-3ms,迴圈約 0.1ms (JIT 優化後差距更大)。| 場景 | 建議 | 理由 |
|---|---|---|
| 樹/圖遍歷 (深度未知) | 遞迴 (程式碼簡潔) | 邏輯天然遞迴,深度通常 < 1000 |
| 分治演算法 | 遞迴 | 合併排序、快速排序、FFT |
| 動態規劃 (備忘錄) | 遞迴 + 記憶化 | 自頂向下直觀 |
| 大量線性迭代 (階乘、費波那契、累加) | 迴圈 | 避免堆疊溢位、效能最佳 |
| BFS / 層序遍歷 | 迴圈 + Queue | 非遞迴本質 |
| 深度可控、邏輯簡單 | 遞迴可接受 | 可讀性優先 |
-Xss2m (治標不治本)。
// 遞迴 (指數複雜度 O(2^n)) - 極慢
long fibRec(int n) { return n <= 1 ? n : fibRec(n-1) + fibRec(n-2); }
// 迴圈 (線性 O(n)) - 快
long fibIter(int n) {
long a = 0, b = 1;
for (int i = 0; i < n; i++) { long t = a + b; a = b; b = t; }
return a;
}
// 矩陣快速冪 / 公式法 (O(log n)) - 最快
**原則:能用迴圈解決的不用遞迴;天然遞迴結構 (樹/圖/分治) 用遞迴但注意深度。**