求解斐波那契数列第n项值
- 大家都知道斐波那契数列,那么现在输入一个整数n,如何快速输出斐波那契数列的第n项呢?
- 公式 : F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2), n >= 2;
公式都给你列好了,那就递归算法先走一个呗~
1. 递归算法
function Febonacci(n) {
if(n < 2) {
return n;
}
return Febonacci(n-1) + Febonacci(n-2);
}
现在来分析一下复杂度:
假如我们现在要求解F(5),那么利用递归算法需要这么求解:
F(5)
F(5) = F(4) + F(3);
F(4) = F(3) + F(2); F(3) = F(2) + F(1);
F(3) = F(2) + F(1); F(2) = F(1) + F(0); F(2) = F(1) + F(0); F(1) = 1;
F(2) = F(1) + F(0); F(1) = 1; F(1) = 1; F(0) =0; F(1) = 1; F(0) = 0 F(1) = 1;
空间复杂度,即递归的深度,每次递归时需要的辅助空间,显而易见的为O(n);
时间复杂度,即递归的次数,可以看出的是该递归呈二叉树形式,递归次数即二叉树节点数2^h-1,h为树的深度,也就是n,所以时间复杂度为O(2^n),(⊙﹏⊙)可能并不会太快得到答案吧。
观察发现在中间计算各项值的时候,存在很多的重复计算,大大消耗了时间,于是我们来做一点优化,把计算过的值存起来,防止重复计算。
2. 时间优化
function Febonacci(n) {
var arr = []; //用于保存每项值
arr[0] = 0, arr[1] = 1; //保存前两项
for(var i = 2; i <= n; i ++) { //循环算出每一项的值,并保存到arr中
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr[n];
}
时间复杂度:O(n)
空间复杂度:O(n)
再仔细观察一下,我们发现每一项值的得出其实只依赖于它的前两项,那么是否可以对空间利用再进行优化呢?
3.空间优化
function Febonacci(n) {
var n_2 = 0; //假设n为2,则n的前两项为0,1
var n_1 = 1;
var n_result = n >= 1 ? 1 : 0; //当n为0或1的时候,直接返回
for(var i = 2; i <= n; i ++) { //n从2开始,依次往后累计
n_result = n_1 + n_2; //第n项的值等于n-1项 + n-2项
n_2 = n_1; //第n-2项的值 变为n-1项的值
n_1 = n_result; //第n-1项的值 变为n项的值
}
return n_result;
}
这时,时间复杂度虽然还是O(n),但是空间复杂度已经降低为O(1)了哟。