求解斐波那切数列的几种算法

来源:互联网 发布:怎么出售域名 编辑:程序博客网 时间:2024/06/11 23:46

斐波那切数列我们并不陌生。在百度百科中我们可以找到有关它的定义:斐波纳契数列(Fibonacci Sequence),又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n>=2,n∈N*)。

斐波那切数列的通项公式为:


我们甚至可以找到它的几个应用:

1.有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第10级台阶有几种不同的走法?
解决:登上第一级台阶有一种登法;登上两级台阶,有两种登法;登上三级台阶,有三种登法;登上四级台阶,有五种登法……
1,2,3,5,8,13……所以,登上十级,有89种走法。

2.一枚均匀的硬币掷10次,问不连续出现正面的可能情形有多少种?

解决:掷一次有2种情况,掷二次有3种情况,掷三次有5种情况...掷10次有144种情况。

3.当n趋于无穷大时,F(n)/F(n+1)的极限是多少?  

解决:这个可由它的通项公式直接得到,极限是(-1+√5)/2,这个就是黄金分割的数值,也是代表大自然的和谐的一个数字。

接下来我们来探讨一下斐波那切数列的一些解决算法:

1.递归算法(是最普遍的解决算法)

int fib(int n){if(n<=1){return n;}else{return fib(n-1) + fib(n-2);}}

这种算法的时间复杂度很高。因为在计算fib(n-1)的时候,把fib(n-2)也给计算了一遍。这样资源得不到重复利用。时间复杂度是指数级的。

2.非递归算法(迭代法)

int fib(int n){int a=0;int b=1;int c;for(int i=2;i<=n;i++){c = a + b;a = b;b = c;}return c;}

这个算法实际上是根据概念走的。比较简单。另外如果想要提高效率,其实可以将三个变量变为两个变量来做:

int fib(int n){int a=0;int b=1;for(int i=2;i<=n;i++){b = a + b;a = b-a;}return b;}


3.矩阵运算:

矩阵运算是能使算法的时间复杂度达到O(logn)的算法,其主要的思路如下:


现在我们主要要知道如何求:。我们可以采用分治法,具体来讲是二分法来解决这个问题:


这样我们容易写出代码:

//定义2×2矩阵;struct Matrix2by2{    //数据成员    int m00;    int m01;    int m10;    int m11;    //构造函数    Matrix2by2(int m_00,int m_01,int m_10,int  m_11)    {        m00 = m_00;        m01 = m_01;        m10 = m_10;        m11 = m_11;    }};//定义2×2矩阵的乘法运算Matrix2by2 MatrixMultiply(const Matrix2by2& matrix1,const Matrix2by2& matrix2){    Matrix2by2 matrix12(1,1,1,0);    matrix12.m00 = matrix1.m00 * matrix2.m00 + matrix1.m01 * matrix2.m10;    matrix12.m01 = matrix1.m00 * matrix2.m01 + matrix1.m01 * matrix2.m11;    matrix12.m10 = matrix1.m10 * matrix2.m00 + matrix1.m11 * matrix2.m10;    matrix12.m11 = matrix1.m10 * matrix2.m01 + matrix1.m11 * matrix2.m11;    return matrix12;}//定义2×2矩阵的幂运算Matrix2by2 MatrixPower(unsigned int n){    Matrix2by2 matrix(1,1,1,0);    if (n == 1)    {        matrix = Matrix2by2(1,1,1,0);    }    else if (n % 2 == 0)    {        matrix = MatrixPower(n / 2);        matrix = MatrixMultiply(matrix, matrix);    }    else if (n % 2 == 1)    {        matrix = MatrixPower((n-1) / 2);        matrix = MatrixMultiply(matrix, matrix);        matrix = MatrixMultiply(matrix, Matrix2by2(1,1,1,0));    }    return matrix;}//计算Fibnacci的第n项int fib(unsigned int n){    if (n == 0)        return 0;    if (n == 1)        return 1;    Matrix2by2 fibMatrix = MatrixPower(n-1);    return fibMatrix.m00;}

4.公式法:


根据这个公式就可以求出第N项,具体代码就不给出了。

5.表驱动的递归法:

这个方法其实是利用递归法的缺点加以改进,在已经计算过的f(n),就不必重复计算了。

#define MAX_LOG 20int Logs[MAX_LOG] = {0};int fib(int n){    if (n <= 1) {        return n;    } else if (n < MAX_LOG && Logs[n] != 0) {        return Logs[n];    } else {        Logs[n] = fib(n - 1) + fib(n - 2);        return Logs[n];    }}

但是在N很大的情况下,不太适用。

6.变形的递归程序。。其实就是迭代法的变形,只不过将while循环或者是for循环的部分变成了递归而已。

int fib_2(int n ,int a ,int b,int count){if(count == n) return b;return fib(n,b,a+b,++count);}int fib(int n){    return fib_2(n,0,1,1);}




原创粉丝点击