斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。
该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
给定 N,计算 F(N)。
1. 递归
递归是最容易想到的一个方法,因为根据题意求每一个索引位置(索引大于2)上的值都等于前两个位置的值相加。
index:1 ——> 1
index:2 ——> 1
index:3 ——> index:2 + index:1
index:4 ——> index:3 + index:2
...
index:n ——> index:n-1 + index:n-2
所以:
var fibonacci = function(index){
if(index <= 0){
return 0;
}
if(index <= 2){
return 1;
}
return arguments.callee(index-1)+arguments.callee(index-2);
}
上述代码中,使用arguments.callee来递归调用自身可以避免将递归调用的函数名写死掉,因为如果将这个函数赋值给了一个新的变量接受后,内部固定的递归调用就会报错。
2. 自顶向下进行数据的暂存
由于每一次递归都会从1开始求到index 这无疑大大浪费了性能,所以可以将数据暂存以下,这样下次再访问小于最大索引的索引值的时候,就是直接获取而不是再去递归。
var arr2 = [0, 1, 1]
var fibonacci2 = function(index) {
if (index <= 0) {
return 0;
}
if (arr2[index]) {
return arr2[index];
}
arr2[index] = arguments.callee(index - 1) + arguments.callee(index - 2);
return arr2[index];
}
对于这个方法,如果第一次求的索引值(index)较大的话,会将这个索引之前的值都求完放进数组,那样之后在求比这个inde小的索引上的值的时候也是可以直接从arr2上面获取,所以会节省很多性能。这是我觉得比较适用的场景。
3. 自下而上进行数据的暂存
var fibonacci = function(index) {
var arr = [0, 1, 1];
for (var i = 3; i <= index; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr[index];
}
相比于第一种递归的方法而言,这里进行一次循环之后会将arr数组中的index索引之前的位置都赋值好,拿最后一次来说,求arr[index]/arr[i]的时候(也就是i==index的时候),arr[i-1]和arr[i-2]上面已经有值了,所以是直接获取而不是再去递归。
4. 循环
因为当前索引上的值会等于前两个索引上的值相加,所以可以设置三个变量来保存,最后返回出来结果。
var fibonacci = function(index) {
if(index <= 0){
return 0;
}
var prev = 1,
next = 1,
sum = 1;
for (var i = 3; i <= index; i++) {
sum = prev + next;
prev = next;
next = sum;
}
return sum;
};
5. 循环优化
从上面的代码中可以发现,实际上只需要两个变量就可以实现了(prev表示前一个索引上的值,now表示现在索引上的值),所以此处对于代码进行一个优化:
var fibonacci = function(index) {
if (index <= 0) {
return 0;
}
var prev = 1,
now = 1;
for (var i = 3; i <= index; i++) {
now = prev + now;
prev = now - prev;
}
return now;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。