返回
解构斐波那契,七种JavaScript实现剖析大法<
前端
2024-01-09 11:14:44
斐波那契数列的定义
斐波那契数列(Fibonacci sequence),又称黄金分割数列,是指这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下递推关系定义:
F(0) = 0, F(1) = 1
F(n) = F(n-1) + F(n-2)(n ≥ 2)
换句话说,斐波那契数列的每一个数字都是由前两个数字之和构成的。
用JavaScript实现斐波那契数列
- 递归法:从后往前解题
这种方法的实现非常直观,也很符合我们对斐波那契数列的认知,因为我们知道斐波那契数列的第N项由它的前两项相加得出,所以我们只需要递归地计算出前两项的值,就能得到第N项的值。
function fibonacci_recursive(n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);
}
}
- 循环法:从前往后解题
循环法从第0项开始依次计算出每项的值,不需要递归调用,循环的次数就是斐波那契数列的项数。
function fibonacci_loop(n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
var first = 0;
var second = 1;
for (var i = 2; i <= n; i++) {
var temp = first + second;
first = second;
second = temp;
}
return second;
}
}
- 递推法:节约空间的循环法
递推法实际上是循环法的优化版本,它利用了斐波那契数列的特点:第N项只与它的前两项有关。所以,我们可以只保存前两项的值,用一个变量来记录当前项的值,循环的次数就是斐波那契数列的项数减去2。
function fibonacci_iterative(n) {
if (n === 0) {
return 0;
} else if (n === 1) {
return 1;
} else {
var first = 0;
var second = 1;
for (var i = 2; i <= n; i++) {
var temp = first;
first = second;
second = temp + second;
}
return second;
}
}
- 动态规划法:利用数组保存中间结果
动态规划法是一种从下到上的解题方法,它利用了斐波那契数列的递推关系,将计算出的中间结果保存在一个数组中,避免了重复计算。
function fibonacci_dp(n) {
var fib = new Array(n + 1);
fib[0] = 0;
fib[1] = 1;
for (var i = 2; i <= n; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
return fib[n];
}
- 生成器法:无需一次性计算出所有结果
生成器法利用了生成器的特性,可以按需计算斐波那契数列的每一项。
function* fibonacci_generator() {
var first = 0;
var second = 1;
while (true) {
yield first;
var temp = first;
first = second;
second = temp + second;
}
}
- 闭包法:利用闭包保存状态
闭包法利用了闭包的特性,可以保存函数内部的变量,从而可以实现斐波那契数列的计算。
function fibonacci_closure() {
var first = 0;
var second = 1;
return function(n) {
if (n === 0) {
return first;
} else if (n === 1) {
return second;
} else {
var temp = first;
first = second;
second = temp + second;
return second;
}
};
}
- 尾递归法:优化递归调用
尾递归法是一种特殊的递归方式,它将递归调用放在函数的最后一行,这样可以优化递归调用的效率。
function fibonacci_tail_recursive(n, first, second) {
if (n === 0) {
return first;
} else if (n === 1) {
return second;
} else {
return fibonacci_tail_recursive(n - 1, second, first + second);
}
}