方法直接或間接調用自身的編程技巧。核心思想:將大問題分解為同性質的小問題,直到達到可直接解決的基本情況(基線條件)。
StackOverflowErrorn! = n × (n-1)!,1! = 1
public static int factorial(int n) {
if (n == 1) return 1; // 基線條件
return n * factorial(n - 1); // 推進 + 返回
}
factorial(5)
5 * factorial(4)
4 * factorial(3)
3 * factorial(2)
2 * factorial(1) → 返回 1
返回 2
返回 6
返回 24
返回 120
F(1)=1, F(2)=1, F(n)=F(n-1)+F(n-2) (n>2)
public static int fib(int n) {
if (n == 1 || n == 2) return 1; // 基線條件
return fib(n - 1) + fib(n - 2); // 推進 + 返回
}
遞歸樹存在大量重複計算,時間複雜度 O(2^n)。fib(40) 已明顯卡頓,fib(50) 可能跑不出結果。
Map<Integer, Integer> memo 緩存結果,降為 O(n)O(n) 時間、O(1) 空間O(log n),適合極大 n// 備忘錄版
private static Map<Integer, Integer> memo = new HashMap<>();
public static int fibMemo(int n) {
if (n <= 2) return 1;
if (memo.containsKey(n)) return memo.get(n);
int res = fibMemo(n - 1) + fibMemo(n - 2);
memo.put(n, res);
return res;
}
public void listFiles(File dir) {
File[] files = dir.listFiles();
if (files == null) return; // 基線條件:空目錄或無權限
for (File f : files) {
if (f.isDirectory()) {
listFiles(f); // 遞歸推進
} else {
System.out.println(f.getAbsolutePath()); // 處理文件
}
}
}
| 維度 | 遞歸 | 迭代 |
|---|---|---|
| 可讀性 | 高(符合數學定義) | 中(需手動維護狀態) |
| 性能 | 棧開銷大,險爆棧 | 高,無棧風險 |
| 適用場景 | 樹/圖遍歷、分治、回溯、DP | 線性遍歷、簡單累加 |
| 尾遞歸優化 | Java 不支持(Scala/Kotlin 支持) | 無需優化 |
StackOverflowError,必寫 if (baseCase) returnfib(n+1)n == 3,觀察調用棧;或打印入參/出參追蹤流程遞歸是解決「自相似」問題的利器。掌握 基線條件、推進邏輯、返回組合 三要素,警惕 重複計算 與 棧溢出。實戰中:樹形結構首選遞歸,線性問題優先迭代,性能敏感處上備忘錄/DP。