斐波那契数列,又称黄金分割数列,因数学家莱昂纳多·斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……斐波那契数列:前两个数之和等于第三个数
根据以上描述,我们可以得出求斐波那契数的公式:
有了以上公式,求斐波那契数我们可以用递归实现,如:我们要求斐波那切数列的第n个数,可以用以下代码实现:
#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 ret = Fib(n);
printf("%d\n", ret);
return 0;
}
我们求第9菲波那切数,其运行结果如下:
但是如果我们用以上代码求菲波那切数列的第50个数的话,该代码至少要运行3分钟以上(虽然结果是错误的,因为第50个斐波那契数已经超出了int的范围),所以其效率太低,究其原因是什么呢?
我们会发现在递归的时候,会进行大量重复的计算,例如我们要求,则需要求5次
在以上代码我们设置一个计数器count,我们统计一下在求第40个斐波那契数的过程中,会计算多少次第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 ret = Fib(n);
printf("%d\n", ret);
printf("count = %d\n", count);
return 0;
}
我们看到count=39088169,可以看到进行了大量重复的计算!
因此,我们可以考虑使用迭代来计算,设置3个变量a、b、c,前两个分别是数列的前两个值1、1,当要求第n(n>=2)个数的时候,设置循环,把前两变量的和放到c中,把b的值赋给a,再把c的值赋给b,最终c里面存放的就是要求的结果
#include <stdio.h>
int Fib(int x)
{
int a = 1;
int b = 1;
int c = 1;
while(x > 2)
{
c = a + b;
a = b;
b = c;
x--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d\n",ret);
return 0;
}