斐波那契数列(简单) yinshibanxian

一、题目描述

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例1

输入:n = 2
输出:1

示例2

输入:n = 5
输出:5

提示

0 <= n <= 100

二、题目解析

  1. 递归法

    如果没有时间上的限制,斐波那契的一般解决方法是递归的方法。

     /**
     * @param {number} n
     * @return {number}
     */
     var fib = function(n) {
         if(n < 2) return n;
         return fib(n-1)  + fib(n-2);
     };
    

    但是这种方法会有大量重复的计算,导致超出leetcode的时间限制

  2. 记忆递归法

    上面说到,未经优化的递归法会进行大量重复的计算,以fibonacci(5)为例

    fibonacci(5) = fibonacci(4) + fibonacci(3); fibonacci(4) = fibonacci(3) + fibonacci(2);

    可以看到,重复计算了fibonacci(3)两次。

    为了减少这种重复计算,我们可以将计算过的结果保存起来,确保不会进行重复的计算。

     /**
     * @param {number} n
     * @return {number}
     */
     var fib = function(n) {
         const memo = [0,1];
         const fibonacci = function(n) {
             if(memo[n] != null) {
                 return memo[n] % 1000000007;
             }
             return memo[n] = (fibonacci(n-1) + fibonacci(n-2)) % 1000000007;
         }
         return fibonacci(n);
     };
    
  3. 动态规划法

    从计算效率、空间复杂度上看,动态规划是本题的最佳解法。

    动态规划解析

    • 状态定义: 设dp为以为数组,其中dp[i]的值代表斐波那契数列第i个数字
    • 转移方程: dp[i] = dp[i-1] + dp[i-2],即对应数列定义f(n) = f(n-1) + f(n-2)
    • 初始状态: dp[0] = 0,dp[1] = 1,即初始化前两个数字
    • 返回值: dp[n],即斐波那契数列的第n个数字
     /**
     * @param {number} n
     * @return {number}
     */
     var fib = function(n) {
         const dp = [0,1];
         for(let i = 2;i <= n;i ++) {
             dp[i] = (dp[i-1] + dp[i-2]) % 1000000007;
         }
         return dp[n];
     };
    
    • 时间复杂度: O(n)
    • 空间复杂度: O(n)

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof