戳蓝字"
前端优选
"
关注我们哦
!
斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列“,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用。
递归实现
function fibonacci(n){
if(n < 0) throw new Error('输入的数字不能小于0');
if(n==1 || n==2){
return 1;
}else{
return fibonacci1(n-1) + fibonacci1(n-2);
}
}
优点:代码递归调用,思路清晰易懂
缺点:当数值较大时,计算速度会立即变慢,原因在于递归时每次都会重复调用前面的计算,从而造成不必要的性能浪费,因此这种方法在时间复杂度上表现并不好
闭包保存递归值
function fibonacci(n){
if(n < 0) throw new Error('输入的数字不能小于0');
let arr = [0,1];//在外部函数中定义数组,内部函数给数组添加值
function calc(n){
if(n<2){
return arr[n];
}
if(arr[n] != undefined){
return arr[n];
}
let data = calc(n-1) + calc(n-2);//使用data将每次递归得到的值保存起来
arr[n] = data;//将每次递归得到的值放到数组中保存
return data;
}
return calc(n);
}
很显然,上次计算的值被保存起来,节省了很多性能。
数组实现
function fibonacci(n){
var a = [0,1,1];
if(n < 0) throw new Error('输入的数字不能小于0');
if(n >= 3){
for(var i=3;i<=n;i++){
a[i] = a[i-1]+a[i-2];
}
}
return a[n];
}
将计算过的值保存起来,后续可以直接调用,也可以节省性能
变量实现
function fibonacci(n) {
var prev = 0; //前一个值
var next = 1; //后一个值
var curr; //当前值
if (n < 0) throw new Error('请输入大于0的值!');
if (n == 0) return 0;
if (n == 1) return 1;
if (n > 2) {
for (var i = 2; i <= n; i++) {
curr = prev + next;
prev = next;
next = curr;
}
}
return curr;
}
该方式优点在于节省内存,缺点在于以前计算的值会被替换掉。
总结
直观的计算思路使用递归即可实现,但在时间复杂度来看不是一个很好的方法,那么就需要通过空间换取时间,将计算出的值保存下来,以免重复计算。
斐波那契数列不仅用于描述兔子繁殖问题,在其他应用中也有广泛的案例,例如:
有个100级阶台阶,一次可以走一个台阶,也可以走两个台阶,走100级台阶有多少种走法(可以把100换为n)
有一个2×1的矩形卡片,可以横着或者竖着去覆盖一个更大的矩形,用n个2×1卡片覆盖一个2×n矩形,有多少种覆盖方法
现有144cm长的铁丝,要截成n段(n>2),且每段长度不小于1cm,如果任意3小段都不能拼成三角形,则n的最大值为多少
大多数植物的花瓣数都正好是斐波那契数
随着数列项数的增加,前一项与后一项之比越来越逼近黄金分割的数值 0.6180339887
点个在看,大家都看