求斐波那契数列第n项的值

请添加图片描述
本期介绍🍖
主要介绍:什么是斐波那契数列,递归实现求斐波那契数列第n项值,递归法为什么不适合求斐波那契数,用迭代法实现求斐波那契数列的值👀。



1. 斐波那契数列是什么?

  斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55,89…这个数列从第3项开始,之后的每一项都等于前两项之和。


2. 题目

  求解:斐波那契数列第n项的值。


2. 递归实现思路

  斐波那契数有一个特性,每一个斐波那契数都是前两个斐波那契数的和。由此当想要求第n个斐波那契数时,就可以写成:Fib(n) = Fib(n-1)+Fib(n-2)。这样求第n个斐波那契数,就转化为求第(n-1)和第(n-2)个斐波那契数了。如此就可以层层转化下去,直至求第1和第2个斐波那契数,公式如下:
在这里插入图片描述

  实现代码如下:

#include<stdio.h>
int Fib(int n)
{
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int back = Fib(n);
	printf("第%d个斐波那契数为>:%d\n", n, back);
	return 0;
}

  当使用上面的代码计算第50个斐波那契数时,会发现运行的代码需要非常久的时间才能算出来。那为什么会这样呢?如下图所示:
在这里插入图片描述

  真正导致计算第50个斐波那契时间过长的原因,是由于在递归的过程中会有重复计算,而且层数越深,冗余计算就越多。可以通过计算求第30个斐波那契数中Fib(3)被重复调用的次数,代码如下:

#include<stdio.h>
int count = 0;
int Fib(int n)
{
	if (n == 3)
		count++;
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int back = Fib(n);
	printf("计算Fib(3)的次数>:%d\n", count);
	printf("第%d个斐波那契数为>:%d\n", n, back);
	return 0;
}

在这里插入图片描述

  当计算第30个斐波那契数,重复计算Fib(3)的次数高达317811,所以可以看出用递归实现计算斐波那契数,是非常不明智的,于是思考如何使用迭代解决。
  大家因该有一个疑惑,重复如此多次递归调用,斐波那契数列为什么没有出现栈溢出的情况?值得注意,不是重复计算多了就会出现栈溢出,而是同时压栈的层数太多才会导致栈溢出。虽然一眼望去该函数需要递归大约 249 次,但这并不代表该函数同时压栈的层数深。因为Fib()的执行逻辑是,先递推一条分支到头,再逐步回归,再递推如此往复。Fib(50)递归最深也就50个调用堆栈。


3. 迭代实现思路

  除了递归法还可以通过迭代法来求第n项的斐波那契数列,因为不管是递归还是迭代其本质都是循环,无非就是正向思维和反向思维之区别。
  迭代法思路:从项斐波那契数的第1项开始,然后通过每一项都等于前两项之和,不断的迭代就可以递推出第n项斐波那契数的值了。

int Fib(int n)
{
	int num1 = 1;
	int num2 = 1;
	int num3 = 1;
	while (n >= 3)
	{
		num3 = num1 + num2;
		num1 = num2;
		num2 = num3;
		n--;
	}
	return num3;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int back = Fib(n);
	printf("第%d个斐波那契数为>:%d\n", n, back);
	return 0;
}

在这里插入图片描述

  如上所示,当计算第50个斐波那契数,一瞬间就的出来了,只不过int类型存不下这个数,打印结果才是一个负数。
  在很多实际问题中,我们可以用递归来解决也可以用非递归来是解决,而有时用递归去解决问题的时候会存在一些问题,就譬如刚刚求斐波那契数列的问题的效率低下。所以碰到这类问题时我们就不能再使用递归的方法了,我们需要另辟蹊径从另一个角度来思考对策,就譬如迭代的方法。


在这里插入图片描述

这份博客👍如果对你有帮助,给博主一个免费的点赞以示鼓励欢迎各位🔎点赞👍评论收藏⭐️,谢谢!!!
如果有什么疑问或不同的见解,欢迎评论区留言欧👀。

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值