遞歸是程式設計中解決「問題可分解為相同子問題」的強大技術。本文透過兩個經典範例——階乘計算與費波那契數列——詳細拆解遞歸的三要素:終止條件、遞歸規律、回溯邏輯。
n! = n × (n-1) × ... × 1,其中 1! = 1 (終止條件)。
if (n == 1) return 1;n * factorial(n-1)public class FactorialDemo {
public static int factorial(int n) {
if (n == 1) { // 終止條件
return 1;
}
return n * factorial(n - 1); // 遞歸規律
}
public static void main(String[] args) {
System.out.println("5! = " + factorial(5)); // 輸出 120
}
}
factorial(5)
→ 5 * factorial(4)
→ 4 * factorial(3)
→ 3 * factorial(2)
→ 2 * factorial(1)
→ 1 (命中終止條件,開始回溯)
→ 2 * 1 = 2
→ 3 * 2 = 6
→ 4 * 6 = 24
→ 5 * 24 = 120
F(1)=1, F(2)=1, F(n)=F(n-1)+F(n-2) (n≥3)。
if (n==1 || n==2) return 1;fib(n-1) + fib(n-2)public class FibonacciDemo {
public static int fib(int n) {
if (n == 1 || n == 2) { // 終止條件
return 1;
}
return fib(n - 1) + fib(n - 2); // 遞歸規律
}
public static void main(String[] args) {
System.out.println("第 9 項: " + fib(9)); // 輸出 34
}
}
費波那契遞歸存在大量重複計算 (時間複雜度 O(2^n))。例如 fib(5) 會重複計算 fib(3)、fib(2) 多次。
Map<Integer, Integer> 快取已計算結果,降至 O(n)。public class FibonacciOptimized {
private static Map<Integer, Integer> cache = new HashMap<>();
public static int fib(int n) {
if (n == 1 || n == 2) return 1;
if (cache.containsKey(n)) return cache.get(n);
int result = fib(n - 1) + fib(n - 2);
cache.put(n, result);
return result;
}
}
遞歸代碼簡潔優雅,但需警惕效能與棧溢位風險。階乘屬於線性遞歸 (單路徑),費波那契屬於樹狀遞歸 (多路徑、重疊子問題) —— 理解兩者差異是掌握遞歸優化的關鍵。