遞歸是解決「問題可分解為同類子問題」的利器。以 1+2+...+n 為例,展示兩種遞歸寫法並分析優缺點,最後給出迭代替代方案。
public class Student {
private int sum = 0; // 實例變量保持狀態
public void sum(int num) {
this.sum += num--;
if (num > 0) {
sum(num); // 遞歸調用
} else {
System.out.println("sum = " + sum);
}
}
}
特點:利用實例字段保存中間結果,邏輯直觀。
缺點:非線程安全、污染對象狀態、非尾調用優化(Java 不保證 TCO),大 n 易棧溢出。
public class Test {
public static int sum(int num) {
if (num == 1) return 1; // 基準情況
return num + sum(num - 1); // 遞歸分解
}
public static void main(String[] args) {
System.out.println(sum(100)); // 5050
}
}
優勢:無副作用、可並行、易測試、符合函數式思維。
同樣風險:棧深度受限,n > 10,000 通常拋 StackOverflowError。
public static int sumLoop(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) sum += i;
return sum;
}
public static int sumWhile(int n) {
int sum = 0;
while (n > 0) sum += n--;
return sum;
}
public static int sumFormula(int n) {
return n * (n + 1) / 2;
}
| 方法 | 時間複雜度 | 空間複雜度 | 適用場景 |
|---|---|---|---|
| 遞歸 | O(n) | O(n) 棧幀 | 教學演示、樹形結構遍歷 |
| 迭代 | O(n) | O(1) | 通用累加、生產環境首選 |
| 數學公式 | O(1) | O(1) | 等差數列、極大 n 值 |
Stream API:LongStream.rangeClosed(1, n).sum()理解遞歸本質,靈活選擇工具,才是工程師的基本功。