「一對兔子,三個月性成熟,之後每月產一對,兔子永不死,求每月總對數」——這是著名的費波那契數列問題,也是遞歸、動態規劃、矩陣快速冪等算法的絕佳入門案例。本文從建模分析到多種 Java 實現,幫你徹底吃透這道經典題。
規律:F(n) = F(n-1) + F(n-2)(n ≥ 3),F(1)=1, F(2)=1。即費波那契數列:1, 1, 2, 3, 5, 8, 13, 21, 34, 55...
public long fibRecursive(int n) {
if (n <= 2) return 1;
return fibRecursive(n-1) + fibRecursive(n-2);
}
Map<Integer, Long> memo = new HashMap<>();
public long fibMemo(int n) {
if (n <= 2) return 1;
if (memo.containsKey(n)) return memo.get(n);
long res = fibMemo(n-1) + fibMemo(n-2);
memo.put(n, res);
return res;
}
public long fibIterative(int n) {
if (n <= 2) return 1;
long a = 1, b = 1;
for (int i = 3; i <= n; i++) {
long c = a + b;
a = b;
b = c;
}
return b;
}
| F(n) | | 1 1 |^(n-2) | F(2) | | F(n-1) | = | 1 0 | | F(1) |
public long fibMatrix(long n) {
if (n <= 2) return 1;
long[][] base = {{1,1},{1,0}};
long[][] res = matrixPow(base, n-2);
return res[0][0] + res[0][1]; // F(2)+F(1)
}
private long[][] matrixPow(long[][] m, long p) {
long[][] result = {{1,0},{0,1}}; // 單位矩陣
while (p > 0) {
if ((p & 1) == 1) result = multiply(result, m);
m = multiply(m, m);
p >>= 1;
}
return result;
}
private long[][] multiply(long[][] a, long[][] b) {
return new long[][]{
{a[0][0]*b[0][0]+a[0][1]*b[1][0], a[0][0]*b[0][1]+a[0][1]*b[1][1]},
{a[1][0]*b[0][0]+a[1][1]*b[1][0], a[1][0]*b[0][1]+a[1][1]*b[1][1]}
};
}
BigInteger 防溢出。F(n) = (φ^n - ψ^n) / √5, φ=(1+√5)/2, ψ=(1-√5)/2
| 變體條件 | 遞推關係 | 應用場景 |
|---|---|---|
| 兔子壽命 m 月 | F(n) = F(n-1) + F(n-2) - F(n-m-1) | 生態建模、緩存淘汰 |
| 每對產 k 對 | F(n) = F(n-1) + k*F(n-2) | 病毒傳播、分叉增長 |
| 成熟需 k 月 | F(n) = F(n-1) + F(n-k) | 項目孵化、技能成長 |