斐波那契數,通常用 F(n) 表示,形成的序列稱為 斐波那契數列 。該數列由 0 和 1 開始,後面的每一項數字都是前面兩項數字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
給你 n ,請計算 F(n) 。
解題思路
斐波那契數是一道非常經典的題目,可以使用暴力遞迴,也可以使用動態規劃等方法。本題給出四種解答,分別是
- 程式碼1 —— 暴力題解
- 程式碼2 —— 使用帶備忘錄的遞迴解法
- 程式碼3 —— dp陣列的動態規劃方法
- 程式碼4 —— 迭代,優化空間複雜度
程式碼1 —— 暴力題解
class Solution {
public int fib(int n) {
// base case
if (n == 0 || n == 1) {
return n;
}
// 遞推關係
return fib(n - 1) + fib(n - 2);
}
}
時間複雜度:O(2^N)
空間複雜度:O(1)
程式碼2 —— 帶備忘錄的遞迴解法
class Solution {
public int fib(int n) {
// 備忘錄全部初始化為0
int[] memo = new int[n + 1];
// 進行帶備忘錄的遞迴
return helper(memo, n);
}
private int helper(int[] memo, int n) {
// base case
if (n == 0 || n == 1) {
return n;
}
// 進行檢查,已經計算過就不用在計算了
if (memo[n] != 0) {
return memo[n];
}
memo[n] = helper(memo, n - 1) + helper(memo, n - 2);
return memo[n];
}
}
時間複雜度:O(N)
空間複雜度:O(N)
程式碼3 —— 使用 dp 陣列的動態規劃方法
class Solution {
public int fib(int n) {
if (n == 0) {
return 0;
}
int[] dp = new int[n + 1];
// base case
dp[0] = 0; dp[1] = 1;
// 狀態轉移
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
}
時間複雜度:O(N)
空間複雜度:O(N)
程式碼4 —— 迭代,優化空間複雜度
class Solution {
// 優化空間複雜度
public int fib(int n) {
if (n == 0 || n == 1) {
return n;
}
// 遞推關係
int prev = 0, curr = 1;
for (int i = 2; i <= n; i++) {
int sum = prev + curr;
prev = curr;
curr = sum;
}
return curr;
}
}