斐波那契数列的四种写法

问题描述

斐波那契数列 :1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... 求第n个数是多少

大概的思路

  1. 递归
  2. 利用数组
  3. 动态规划
  4. 尾递归

四种写法

function fibonacci(num) {
	if(num <=0 ){
		return;
	}
	if( num === 1 && num ===2) {
		return 1;
	}
	return fibonacci(num-1) + fibonacci(num-2);
}

function fibonacci2(num) {
	let arr = [1, 1];
	if(num <=0 ){
		return;
	}
	if(num === 1 && num === 2) {
		return 1;
	}
	for(let i = 2; i < num; i++) {
		arr[i] = arr[i-1] +arr[i-2];
 	}
	return arr[num-1];
}

function fibonacci3(num) {
	var pre = 1;
	var next = 1;
	if(num <= 0 ){
		return;
	}
	for(let i = 2; i < num; i++) {
		let temp = pre;
		pre =  next;
		next = pre + temp;
		//或写成:
		//next = pre + next;
		//pre = next - pre;
	}
	return next;

}

function fibonacci4(n, a = 1, b = 1) {
  if (n === 1) return a;
  return fibonacci4(n - 1, b, a + b)
}

console.log(fibonacci(-1));

console.log(fibonacci2(10));

console.log(fibonacci3(10));

console.log(fibonacci4(10));
复制代码

几个问题?

  1. 什么是动态规划?
    1.将一个原问题分解为若干个规模较小的子问题,递归的求解这些子问题
    2.一个子问题在求解后,可能会再次求解,于是我们想到将这些子问题的解存储起来,当下次再次求解这个子问题时,直接拿过来使用。

  2. 复习时间、空间复杂度概念?
    O(n): for循环里面的代码会执行 n 遍,因此它消耗的时间是随着 n 的变化而变化的,因此可以用O(n)来表示它的时间复杂度。
    O(n²): 当存在双重循环的时候,即把 O(n) 的代码再嵌套循环一遍,它的时间复杂度就是 O(n²) 了。
    O(logn) :在二分查找法的代码中,通过while循环,成 2 倍数的缩减搜索范围,也就是说需要经过 log2^n 次即可跳出循环。
    O(nlogn): 将时间复杂度为O(logn)的代码循环N遍的话,那么它的时间复杂度就是 n * O(logn),也就是了O(nlogn)。
    总结: O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2ⁿ)<O(n!)

    空间复杂度可以理解为除了原始序列大小的内存,在算法过程中用到的额外的存储空间。

  3. 递归算法的时间复杂度
    如果递归函数中,只进行一次递归调用,递归深度为depth; 在每个递归的函数中,时间复杂度为T; 则总体的时间复杂度为O(T * depth)。

  4. 以上四种写法的时间复杂度和空间复杂度?
    1.递归写法:
    时间复杂度: O(2^n)

    当n=4,需要累加3 和 2 的次数,3 和 2 又一直调用 n-1 和 n-2的结果,可以画成成一棵二叉树,总的计算量近似可以等于高度为n-1的二叉树的节点总数,所以它的时间复杂度为O(2^n)
    2^0 + 2^1 + 2^2 + ...... + 2^n = 2^(n+1) - 1 = O(2^n)

    空间复杂度:O(n)
    n个叶子节点,n个调用栈

    2.利用数组:
    时间复杂度: O(n) for一次循环
    空间复杂度:O(n) 数组长度为n

    3.动态规划:
    时间复杂度: O(n) for循环了一遍
    空间复杂度:O(1)

    4.尾递归:
    时间复杂度为 O(n) 计算执行了n次
    空间复杂度为 O(1) 只有一个调用栈

总结:

斐波拉契数列,可以用几种方法来写,每个方法都有不同的时间、空间复杂度,当然还可以利用generator生成器等方法来写,我学的不好,就不写了。
本人才疏学浅,如有错误,还望指正。

参考文章:

从斐波那契数列谈谈代码的性能优化
冰与火之歌:「时间」与「空间」复杂度
看动画轻松理解「递归」与「动态规划」
JavaScript调用栈、尾递归和手动优化
尾调用和尾递归

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值