Sword10- I——斐波那契数列

Sword10- I——斐波那契数列

方法1——动态规划

  • 思路:
    • 确定状态:dp为一维数组,第n个元素为dp[n]
    • 转移方程:F(N) = (F(N - 1) + F(N - 2)) % 1000000007
    • 初始状态和边界情况:F(0) = 0,F(1) = 1
    • 计算结果:dp[n]即为第n个元素
  • 特殊情况与临界分析:F(0) = 0,F(1) = 1
  • 终止条件:第n项时直接返回
  • 步骤:
    • 当n为0、1时,需要单独处理
    • 定义dp数组,因为dp[n]存在于n+1长度的数组中
    • 定义第0项与第1项的值
    • for循环,i从2开始,但是可以等于n
      • 求出下一项的值dp[i],需要对结果取模1000000007
    • 返回dp[n]即为结果值
    public int fib(int n) {
        // n为0时,返回0
        if (n == 0) {
            return 0;
        }
        // n为1时,返回1
        if (n == 1) {
            return 1;
        }
        // 定义dp数组
        int[] dp = new int[n + 1];
        // 定义第0项与第1项
        dp[0] = 0;
        dp[1] = 1;
        // for循环
        for (int i = 2; i <= n; i++) {
            dp[i] = (dp[i - 2] + dp[i - 1]) % 1000000007;
        }
        // 返回结果dp[n]
        return dp[n];
    }
  • 优化:对上述两个特殊情况做合并
    • 可以将for循环更改为从0开始
    • 当n为0时,相当于跳过for循环直接返回cur为0
    • 当n为1时,for循环执行一次,返回的cur为之前的next为1
    • 综上所述,两种特殊情况都包含在内
    public int fib(int n) {
        // 定义dp数组
        int[] dp = new int[n + 1];
        // 定义第0项与第1项
        dp[0] = 0;
        dp[1] = 1;
        // for循环
        for (int i = 2; i <= n; i++) {
            dp[i] = (dp[i - 2] + dp[i - 1]) % 1000000007;
        }
        // 返回结果dp[n]
        return dp[n];
    }
  • 优化
    • 当n较大时,dp数组前面的元素已经无用还占据空间
    • 因此可以仅用几个变量来代替dp数组
    public int fib(int n) {
        // 定义第0项和第1项
        int cur = 0, next = 1, tmp = 0;
        // for循环
        for (int i = 0; i < n; i++) {
            // 求出下一项的值
            tmp = (cur + next) % 1000000007;
            // cur赋给pre
            cur = next;
            // tmp赋给cur
            next = tmp;
        }
        // 返回cur
        return cur;
    }

Sword10- I——斐波那契数列

上一篇:【剑指offer】剪绳子


下一篇:剑指 Offer 10- I. 斐波那契数列 + 剑指 Offer 10- II. 青蛙跳台阶问题