C语言练习---求第n个斐波那契数(不考虑溢出)。
斐波那契数列:1,1,2,3,5,8,13,21,34,55,89........
这个数列从第3项开始,每一项都等于前两项之和。
在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
方法一:递归法
可以从数学计算方式上知道,第F(n)个斐波那契数的值为:F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
#include <stdio.h>
#include <stdlib.h>
//斐波那契数列为:
//1 1 2 3 5 8 13 21 34 55 89
int Fib (int n)
{
if(n<=2)
return 1;//如果n小于等于2,则返回1
else
return Fib(n-1)+Fib(n-2);//如果n大于2,第n个斐波那契数为,前面两个数相加
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d",&n); //输入需要查询第n个数
ret = Fib(n); //将函数返回值赋给ret,并打印出来
printf("%d",ret);
return 0;
}
执行结果为:
大家可以试试求第50个斐波那契数,可以发现,计算机需要很长的时间才能计算出第50个斐波那契数,效率极其地低。
这是为什么呢?因为要求第50个数,需要找到第49和48这两个数,49又需要计算出48和47的值,48需要计算出47和46的值……
在这个倒推的过程中,很多数字被重复计算了很多次,导致效率变低。
添加部分代码,测试计算第20个数,第3个斐波那契数会重复计算几次
#include <stdio.h>
#include <stdlib.h>
//斐波那契数列为:
//1 1 2 3 5 8 13 21 34 55 89
int count; //定义一个全局变量,count
int Fib (int n)
{
if(n==3)
{
count ++; //测试计算到第三个斐波那契数时,会被计算几次
}
if(n<=2)
return 1;//如果n小于等于2,则返回1
else
return Fib(n-1)+Fib(n-2);//如果n大于2,第n个斐波那契数为,前面两个数相加
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d",&n);
ret = Fib(n);
printf("%d\n",ret);
printf("count =%d\n",count);
return 0;
}
可见,第3个斐波那契数被重复计算了2584次,使得效率很低。
方法二:循环法
使用倒推的方式会导致效率变慢,那我们就使用正推的方法。
定义三个数,c表示第n个斐波那契数,c = a +b。
观察下图,可以发现,进入下一轮循环是,a的值也就是b的值,b的值也就是c的值
#include <stdio.h>
#include <stdlib.h>
int Fib( int n)
{
int a = 1;
int b = 1;
int c = 1; //将c的初始值设置为1,这样当n<=2时,返回c,也就是1
while(n>2)
{
c = a+b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d",&n);
ret = Fib(n);
printf("%d\n",ret);
return 0;
}
执行结果为: