剑指 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
注意,上面的是官方标识的【精选题解】
【更新结束】
有关参考
更新:2021年8月12日15:13:50
参考:JavaScript pow() 方法
参考:算法图解part3:递归&栈_catkin_ws的博客-CSDN博客
参考:【算法-LeetCode】53. 最大子序和_赖念安的博客-CSDN博客
参考:【算法-LeetCode】70. 爬楼梯_赖念安的博客-CSDN博客