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

原地址:http://blog.csdn.net/niuox/article/details/7252674#comments

斐波那切数列我们并不陌生。在百度百科中我们可以找到有关它的定义:斐波纳契数列(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.递归算法(是最普遍的解决算法)

[cpp]  view plain  copy
  1. int fib(int n)  
  2. {  
  3.     if(n<=1)  
  4.     {  
  5.         return n;  
  6.     }  
  7.     else  
  8.     {  
  9.         return fib(n-1) + fib(n-2);  
  10.     }  
  11.       
  12. }  

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

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

[cpp]  view plain  copy
  1. int fib(int n)  
  2. {  
  3.     int a=0;  
  4.     int b=1;  
  5.     int c;  
  6.     for(int i=2;i<=n;i++)  
  7.     {  
  8.         c = a + b;  
  9.         a = b;  
  10.         b = c;  
  11.           
  12.     }  
  13.     return c;  
  14.       
  15.       
  16. }  

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

[cpp]  view plain  copy
  1. int fib(int n)  
  2. {  
  3.     int a=0;  
  4.     int b=1;  
  5.     for(int i=2;i<=n;i++)  
  6.     {  
  7.         b = a + b;  
  8.         a = b-a;  
  9.     }  
  10.     return b;  
  11.       
  12.       
  13. }  


3.矩阵运算:

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


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


这样我们容易写出代码:

[cpp]  view plain  copy
  1. //定义2×2矩阵;  
  2. struct Matrix2by2  
  3. {  
  4.     //数据成员  
  5.     int m00;  
  6.     int m01;  
  7.     int m10;  
  8.     int m11;  
  9.     //构造函数  
  10.     Matrix2by2(int m_00,int m_01,int m_10,int  m_11)  
  11.     {  
  12.         m00 = m_00;  
  13.         m01 = m_01;  
  14.         m10 = m_10;  
  15.         m11 = m_11;  
  16.     }  
  17.   
  18. };  
  19.   
  20. //定义2×2矩阵的乘法运算  
  21. Matrix2by2 MatrixMultiply(const Matrix2by2& matrix1,const Matrix2by2& matrix2)  
  22. {  
  23.     Matrix2by2 matrix12(1,1,1,0);  
  24.     matrix12.m00 = matrix1.m00 * matrix2.m00 + matrix1.m01 * matrix2.m10;  
  25.     matrix12.m01 = matrix1.m00 * matrix2.m01 + matrix1.m01 * matrix2.m11;  
  26.     matrix12.m10 = matrix1.m10 * matrix2.m00 + matrix1.m11 * matrix2.m10;  
  27.     matrix12.m11 = matrix1.m10 * matrix2.m01 + matrix1.m11 * matrix2.m11;  
  28.     return matrix12;  
  29.   
  30. }  
  31.   
  32.   
  33. //定义2×2矩阵的幂运算  
  34. Matrix2by2 MatrixPower(unsigned int n)  
  35. {  
  36.     Matrix2by2 matrix(1,1,1,0);  
  37.     if (n == 1)  
  38.     {  
  39.         matrix = Matrix2by2(1,1,1,0);  
  40.     }  
  41.     else if (n % 2 == 0)  
  42.     {  
  43.         matrix = MatrixPower(n / 2);  
  44.         matrix = MatrixMultiply(matrix, matrix);  
  45.     }  
  46.     else if (n % 2 == 1)  
  47.     {  
  48.         matrix = MatrixPower((n-1) / 2);  
  49.         matrix = MatrixMultiply(matrix, matrix);  
  50.         matrix = MatrixMultiply(matrix, Matrix2by2(1,1,1,0));  
  51.     }  
  52.     return matrix;  
  53. }  
  54. //计算Fibnacci的第n项  
  55. int fib(unsigned int n)  
  56. {  
  57.     if (n == 0)  
  58.         return 0;  
  59.     if (n == 1)  
  60.         return 1;  
  61.   
  62.     Matrix2by2 fibMatrix = MatrixPower(n-1);  
  63.     return fibMatrix.m00;  
  64.   
  65. }  

4.公式法:


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

5.表驱动的递归法:

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

[cpp]  view plain  copy
  1. #define MAX_LOG 20  
  2. int Logs[MAX_LOG] = {0};  
  3. int fib(int n)  
  4. {  
  5.     if (n <= 1) {  
  6.         return n;  
  7.     } else if (n < MAX_LOG && Logs[n] != 0) {  
  8.         return Logs[n];  
  9.     } else {  
  10.         Logs[n] = fib(n - 1) + fib(n - 2);  
  11.         return Logs[n];  
  12.     }  
  13. }  
  14.       

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

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

[cpp]  view plain  copy
  1. int fib_2(int n ,int a ,int b,int count)  
  2. {  
  3.     if(count == n) return b;  
  4.     return fib(n,b,a+b,++count);  
  5. }  
  6. int fib(int n)  
  7. {  
  8.     return fib_2(n,0,1,1);  
  9. }  
  10.  

你可能感兴趣的:(学习资料)