遞歸是「自己調用自己」解決問題,核心要素:遞歸體(如何分解)+ 終止條件(何時停止)。
int Fib(int n) {
if (n < 3) return 1;
return Fib(n-1) + Fib(n-2); // 指數級調用,極其低效
}
Fib(20) 調用超 1 萬次,棧溢出風險大。
int Fib(int n) {
int a[3] = {1,1,1};
for (int i = 3; i <= n; i++)
a[i%3] = a[(i+1)%3] + a[(i+2)%3];
return a[n%3];
}
遞歸寫法(教學用,不推薦生產):
int sum = 0;
int Acc(int i) {
if (i == 0) return 0;
return sum += Acc(i-1) + 1;
}
規律:f(n) = f(n-1) + f(n-3)(第 n 年新增牛 = 3 年前存活牛數)。
int Cattle(int n) {
if (n < 4) return 1;
return Cattle(n-1) + Cattle(n-3);
}
同樣存在指數級重複計算,循環/備忘錄優化極易實現。
| 維度 | 遞歸 | 循環 |
|---|---|---|
| 代碼簡潔度 | 高(數學定義直譯) | 中等 |
| 空間複雜度 | O(遞歸深度) 棧帧 | O(1) 或 O(n) 數組 |
| 性能 | 函數調用開銷、重複計算風險 | 通常更快 |
| 適用場景 | 樹/圖遍歷、分治、回溯、自然遞歸結構 | 線性疊代、狀態機、高性能要求 |