509.斐波那契数

66 阅读1分钟

509.斐波那契数

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。 该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。 也就是: F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1 给定 n ,请计算 F(n) 。

题解

1.暴力递归

存在重叠子问题(存在大量重复计算,耗时)

 public int fib(int n) {
     if (n == 1 || n == 0) {
         return n;
     }
     return fib(n - 1) + fib(n - 2);
 }

2.带备忘录的递归解法 - 剪枝

每次遇到一个子问题时,先去查备忘录,存在拿出来用,否则计算子问题,答案先记录到备忘录,再返回。

private int[] memo;
public int fib(int n) {
    // 备忘录初始化
    memo = new int[n + 1];
    // 带备忘录的递归
    return f(n);
}
public int f(int n) {
    // base case
    if (n == 0 || n == 1) {
        return n;
    }
    // 查备忘录,存在拿出来用,没有再计算
    if (memo[n] != 0) {
        return memo[n];
    }
    // 每次计算出子问题答案,先记录到备忘录,再返回。
    memo[n] = f(n - 1) + f(n - 2);
    return memo[n];
}

3.动态规划 - 数组的迭代(递推)解法

public int dp(int n) {
    if (n == 0 || n == 1) {
        return n;
    }
    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];
}

4.空间优化

当前状态 n 只和之前的 n-1, n-2 两个状态有关,去掉数组,用两个值替代。

public int dp2(int n) {
    if (n == 0 || n == 1) {
        return n;
    }
    // base case
    int dp_i_2 = 0;
    int dp_i_1 = 1;
    for (int i = 2; i <= n; i++) {
        // 状态转移
        int dp_i = dp_i_1 + dp_i_2;
        dp_i_2 = dp_i_1;
        dp_i_1 = dp_i;
    }
    return dp_i_1;
}