【算法-剑指 Offer】10- I. 斐波那契数列(递归;动态规划)

剑指 Offer 10- I. 斐波那契数列 - 力扣(LeetCode)

发布:2021年8月12日15:09:49

问题描述及示例

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例 1:
输入:n = 2
输出:1

示例 2:
输入:n = 5
输出:5

提示:
0 <= n <= 100

我的题解

我的题解1(递归——因超时而无法通过)

求解斐波那契数列是非常经典的递归应用,但是很可惜的是,LeetCode对于提交的程序的执行时间有一定的限制,而这种递归的方法恰恰非常的耗费时间和空间。当输入的数字到达44时就不能在规定的时间内返回结果了。递归的有关过程解释可以看下方的【有关参考】。

/**
 * @param {number} n
 * @return {number}
 */
var fib = function(n) {
  // 由于递归调用的特殊性,我习惯用一个辅助函数来完成递归逻辑,但是在本题中可以不必这样写
  function fibonacci(num) {
    // 如果输入当前递归的参数为0,则返回0,因为F(0) = 0,这是递归结束条件
    if(num === 0) {
      return 0;
    }
    // 如果输入当前递归的参数为1或2,则返回1,因为F(1) = F(2)= 1,这也是递归结束条件
    // 当然,这里可以不用写num === 2的情况,这样做只是为了减少一次递归嵌套
    if(num === 1 || num === 2) {
      return 1;
    }
    // 开始用递归公式计算数列值
    return fibonacci(num-1) + fibonacci(num-2);
  }
  // 不要忘记把递归的结果返回,如果不用辅助函数,这里可以不用写
  return fibonacci(n);
};

提交记录
24 / 51 个通过测试用例
状态:超出时间限制
时间:2021/08/12 14:35

在这里插入图片描述

我的题解2(动态规划)

上面的解法没有通过,我倒是不意外。所以马上就开始了动态规划的解法,其实这题就是我之前做的【算法-LeetCode】70. 爬楼梯_赖念安的博客-CSDN博客 这道题的简化版。思路完全一样,所以就不做过多的解释了。

当然本题中还有一个附加条件:答案需要取模 1e9+7(1000000007),这里需要注意一下这个取模操作的时机,是在每次计算dp[i]时都要取模,而不是只在最后返回结果时进行取模,这点要特别注意,这应该涉及到内存中保存数字的范围问题。如果只是在最后返回结果时进行取模,则当输入81时,所得的结果会与预期不符。

在这里插入图片描述

注意下面的dp数组初始化条件中的dp[0],在这题中,dp[0]是有意义的,所以不是从dp[1]做初始化。

/**
 * @param {number} n
 * @return {number}
 */
var fib = function(n) {
  let dp = [];
  dp[0] = 0;
  dp[1] = 1;
  for(let i = 2; i <= n; i++) {
    // 这里的 1000000007 也可以用 (Math.pow(10,9) + 7) 代替
    dp[i] = (dp[i - 1] + dp[i - 2]) % 1000000007;
  }
  return dp[n];
};


提交记录
318 / 318 个通过测试用例
状态:通过
执行用时:64 ms, 在所有 JavaScript 提交中击败了93.36%的用户
内存消耗:37.6 MB, 在所有 JavaScript 提交中击败了75.40%的用户
时间:2021/08/12 15:14

如果对递归或者动态规划的过程不大清楚,可以借助Chrome开发者工具的的逐步调试功能进行逐步观察

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年8月12日15:12:44

参考:面试题10- I. 斐波那契数列(动态规划,清晰图解) - 斐波那契数列 - 力扣(LeetCode)

注意,上面的是官方标识的【精选题解】

【更新结束】

有关参考

更新:2021年8月12日15:13:50
参考:JavaScript pow() 方法
参考:算法图解part3:递归&栈_catkin_ws的博客-CSDN博客
参考:【算法-LeetCode】53. 最大子序和_赖念安的博客-CSDN博客
参考:【算法-LeetCode】70. 爬楼梯_赖念安的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值