1.根据公式,直接递归
/**
* 斐波那契数列 F(1)=1 F(2)=1 F(n)=F(n-2)+F(n-1)
*/
/**
* 递归
*/
function Fibonacci_1(n) {
if (n <= 1) {
return n;
}
return Fibonacci_1(n - 2) + Fibonacci_1(n - 1);
}
console.time("Fibonacci_1");
Fibonacci_1(40);
console.timeEnd("Fibonacci_1"); //Fibonacci_1: 899.942ms
简单,根据公式直接写出,但是慢。
时间复杂度:O(2^n)
空间复杂度:递归栈的空间
2.不递归,保存重复计算结果
/**
* 保存计算结果
*/
let map = new Map();
function fib(n) {
let a;
if (map.has(n)) {
a = map.get(n);
} else {
a = Fibonacci_2(n);
map.set(n, a);
}
return a;
}
function Fibonacci_2(n) {
if (n <= 1) {
return n;
}
return fib(n - 2) + fib(n - 1);
}
console.time("Fibonacci_2");
Fibonacci_2(40);
console.timeEnd("Fibonacci_2"); //Fibonacci_2: 0.217ms
可以看到速度比递归快了很多
时间复杂度:O(n)没有重复的计算
空间复杂度:O(n)和递归栈的空间
3.动态规划
/**
* 动态规划
* @param {number}} n
*/
function Fibonacci_3(n) {
// write code here F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)
if (n <= 1) {
return n;
}
let a = 0,
b = 1,
c;
for (let i = 2; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}
console.time("Fibonacci_3");
Fibonacci_3(40);
console.timeEnd("Fibonacci_3"); //Fibonacci_3: 0.143ms
耗时最短。将计算过程拆解,每次计算只需要F(n-2)和F(n-1)的计算结果,不需要存储所有的计算结果。
时间复杂度:O(n)
空间复杂度:O(1)