C#实现斐波拉契数列的两种方式
在实现代码之前,我们首先来看看斐波拉契数列的由来
斐波那契数列(Fibonacci sequence)
又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)(n>=3,n∈N*)在现代物理、准晶体结构、化学等领域,斐波纳契数列都有直接的应用,为此,美国数学会从1963年起出版了以《斐波纳契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。
那什么是兔子数列呢?继续往下看
兔子问题:
历史上有一个有名的关于兔子的问题:假设有一对兔子,长两个月它们就算长大成年了。然后以后每个月都会生出1对兔子,生下来的兔子也都是长两个月就算成年,然后每个月也都会生出1对兔子了。这里假设兔子不会死,每次都是只生1对兔子。
第一个月,只有1对小兔子;
第二个月,小兔子还没长成年,还是只有1对兔子;
第三个月,兔子长成年了,同时生了1对小兔子,因此有两对兔子;
第四个月,成年兔子又生了1对兔子,加上自己及上月生的小兔子,共有3对兔子;
第五个月,成年兔子又生了1对兔子,第三月生的小兔子现在已经长成年了且生了1对小子,加上本身两只成年兔子及上月生的小兔子,共5对兔子;
这样过了一年之后,会有多少对兔子了呢?(思考)
总结:
我们可以把这些兔子的数量以对为单位列出数字就能得到一组数字:1、1、2、3、5、8、13、21、34、55、89、144、233。所以,过了一年之后,总共会有233对兔子了。那么续往下呢?
其实这组数字可以形成一个有规律的数列,我们把这个数列叫做“斐波那契数列”。在这个数列中的数字,就被称为“斐波那契数”。这个数列是在1228年意大利数学家斐波那契首先提出的。这个数列的规律是这样的:它的第一项、第二项是1,而从第三项起每一项都等于它的前两项之和。
实现方式:
第一种方式(递归):
通过重复调用当前方法来进行递归,欲求第n项和第n-1项之和,先求第n-1和n-2项之和…直到得到已知的第一项和第二项的值,再将结果进行回溯,逆推后面的值,得到我们想要的结果值。
此种方法的好处是能够较为直接简便的实现我们需要的功能,且能提高代码的简洁性和可读性,但最大的缺点是运行时间较长(128s),时间复杂度和空间复杂度较高。
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FibonacciSort
{
class Program
{
long Fib(int num){
if (num <3)
{
return 1;
}
else
{
return Fib(num - 1) + Fib(num - 2);
}
}
static void Main(string[] args)
{
//定义一个计时对象
System.Diagnostics.Stopwatch needTime = new System.Diagnostics.Stopwatch();
needTime.Start();
Program Pro = new Program();
Console.WriteLine("第40个元素为:"+ Pro.Fib(40));
Console.WriteLine("第48个元素为:" + Pro.Fib(48));
needTime.Stop();
//运行时间打印
Console.WriteLine("运行时间:" + needTime.Elapsed.TotalSeconds + "s");
}
}
}
运行结果:
在这里需要注意,定时器只为记录运行时间,与数列生成实现无关。
第二种方式(递推):
这种方式主要是通过定义三个不同对象,为他们循环赋值累加以得到最终需要的那个值,具体赋值方式如下。
此方法比较不灵活,需要得到某个数时,需要更改循环次数,否则就会造成数组越界或者内存浪费,但是执行速度极快(0.002s)。
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Fibonacci1
{
class Program
{
static void Main(string[] args)
{
//定义一个计时对象
System.Diagnostics.Stopwatch needTime = new System.Diagnostics.Stopwatch();
needTime.Start();
long a, b, c;
a = 1;
b = 1;
for(int i = 3; i < 49; i++)
{
c = a + b;
a = b;
b = c;
if (i == 40)
{
Console.WriteLine("第40个数为:"+c);
}
if (i == 48)
{
Console.WriteLine("第48个数为:"+c);
}
}
needTime.Stop();
//运行时间打印
Console.WriteLine("运行时间:"+needTime.Elapsed.TotalSeconds+"s");
}
}
}
运行结果:
至于两种实现方式到底哪种更好,笔者觉得要视实际情况而定,在合适的场景,选择合适的实现方式吧。
以上就是全部内容,看过给个关注吧。