(文章参考来源)
https://zhidao.baidu.com/question/2115713113203375747.html
https://www.jianshu.com/p/78243311b8ed
题目
有一对兔子,从出生后第3个月起每个月都生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
分析,每个月份的兔子数(单位:对)是:
1
1
2(T1生了T2)
3(T1生了T3)
5(T1生了T4,T2生了T5)
8(T1生了T6,T2生了T7,T生了T8)
13(T4、T5也加入了生兔子大军)
从数据可见,每个月的兔子数(单位:对)形成了菲波那切数列。
javaScript code
1) 正常递归版本
function fibonacciFunc(n){
if(n == 0)
return 0
else if(n == 1)
return 1
else
return fibonacciFunc(n-1)+fibonacciFunc(n-2)
}
代码优美逻辑清晰。但是这个版本有一个问题即存在大量的重复计算。如:当n为5的时候要计算fibonacci(4) + fibonacci(3)当n为4的要计算fibonacci(3) + fibonacci(2),这时fibonacci(3)就是重复计算了。运行fibonacci(50)等半天才会出结果。
2)for循环版本
function fibonacci(n){
let last = 1
let last2 = 0
let current = last2
for(let i=1; i<= n; i++){
last2 = last
last = current
current = last+last2
}
return current
}
这个版本没有重复计算问题,速度也明显快了很多。这并不代表循环比递归好。循环的问题在于状态变量太多,为了实现fibonacci这里使用了4个状态变量(last,last2,current,i)而状态变量 在写、修改、删除的过程中需要格外小心,它会让我有不安全感。状态变量多了阅读起来也不那么优美了。
3)去除重复计算的递归版本
function fib(n){
function fib_(n, a, b){
if(n == 0)
return a
else
return fib_(n-1, b, a+b)
}
return fib_(n, 0, 1)
}
把前两位数字做成参数巧妙的避免了重复计算,性能也有明显的提升。n做递减运算,前两位数字做递增(斐波那契数列的递增),这段代码一个减,一个增,初看时有点费脑力。按照我的习惯一般是全增,让n从0开始到n。
网友评论