小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
开始
以下用的是JavaScript
有多少同学写出来是下面这段代码的,老实给我站出来😂
const fibonacci = function(n) {
if (n < 2) {
return n
}
return fibonacci(n - 1) + fibonacci(n - 2)
}
这段代码存在两个问题,下面让我们来看看
我们把代码扔进力扣试一下,看看是否能提交成功
可以发现,力扣提示超出时间限制
其实代码本身没错,,我们可以用缓存来优化这段代码
先看一下优化前代码执行时间和优化后代码执行时间。
直接从20s => 0.13ms
解决超出时间限制
思路是这样的,创建一个Map,如果n已经记录,直接返回n对应缓存的值
const map = new Map()
const fibonacci = function(n) {
if (n < 2) {
return n
}
if (map.get(n)) {
// 如果map有了,直接取出
return map.get(n)
}
let result = fibonacci(n - 1) + fibonacci(n - 2)
// 设置到map
map.set(n, result)
return result
}
缓存这块是通用的,在很多地方都可以派上用场,可以提高性能
好!看我们把代码扔进力扣,看看这次是否能提交成功
可以看到,超出时间限制已经解决了,这次提示解答错误
excuse me??? 逻辑应该没问题呀,为什么要提示解答错误
我们看上面那张图,n为45的情况下,预期结果是134903163,但是我们的是:1134903170
我们看到题目里面,有这么一段话
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
为啥要模 1000000007呢?是因为
- 大数相加会超出数值范围
- 1000000007是一个质数(素数),对质数取余能最大程度避免冲突
- int64位的最大值为2^63-1,对于1000000007来说它的平方不会在int64中溢出
最终代码
const map = new Map()
const fibonacci = function(n) {
if (n < 2) {
return n
}
if (map.get(n)) {
// 如果map有了,直接取出
return map.get(n)
}
let result = fibonacci(n - 1) + fibonacci(n - 2)
// 如果计算结果大于1000000007, 对其取模
result >= 1000000007 && (result = result % 1000000007)
// 设置到map
map.set(n, result)
return result
}
可以看到在力扣中成功提交~~
结语
文章内容很low,不喜勿喷。有啥错误或评价可以评论区指出,主要是想让你们看到缓存的作用和数值范围小知识,谢谢