文章来自:http://blog.csdn.net/mshantingting/article/details/22689573

斐波那契数列(又名黄金分割数列)在数学上的定义如下:

许多人包括作者自己在看到这道题的时候,第一个想法就是使用函数递归来实现程序。

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3
 4 long long Fibonacci(int n)
 5 {
 6 long long f;
 7 if(n==1||n==2)
 8 f=1;
 9 else
10 f=Fibonacci(n-1)+Fibonacci(n-2);
11 return f;
12 }
13
14 int main()
15 {
16 int n;
17 long long f;
18 scanf("%d",&n);
19 f=Fibonacci(n);
20 printf("%lld",f);
21 return 0;
22 }

View Code

这种方法虽然便于理解,但是我们考虑一下,它的时间复杂度可是以n的指数形式增长 的。当n=10,n=20或者n=30时,程序能够在我们可以接受的运行时间内反馈给我们运行结果。但是,我们如果试一下n=50的情况,运行时间已经远 远超过了我们能够等待的时间(大概一分半钟)。原因很简单,例如我们要求f(8),就要知道f(7)和f(6),而求f(7)我们要求得f(6)和 f(5),因此我们重复求了很多项,浪费很多时间。
改进的做法也是很简单的,我们可以从小往大算,循环n-1次,根据f(0)和f(1)求出f(2),再根据f(1)和f(2)求出f(3),以此类推。代码实现如下:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3
 4 long long Fibonacci(int n)
 5 {
 6 int result[2]={0,1},i;
 7 if(n<2)
 8 return result[n];
 9 long long One = 1,Two = 0,Current_N = 0;
10 for(i=2;i<=n;i++)
11 {
12 Current_N = One + Two;
13 Two = One;
14 One = Current_N;
15 }
16 return Current_N;
17 }
18
19 int main()
20 {
21 long long n,f;
22 scanf("%d",&n);
23 f=Fibonacci(n);
24 printf("%lld",f);
25 return 0;
26 }

View Code

此方法时间复杂度是O(n)。这种方法提高了时间效率,被很多人采用。那还有没有更快的方法呢?根据《剑指offer》一书中作者提到的方法,书中介绍了一个数学公式如下:

我进行了如下验算:

因此f(n)就等于等式右边的二阶方阵的(n-1)次方所求得方阵的第一行第一列个数的值。代码实现如下:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstdlib>
 4
 5 using namespace std;
 6
 7 //求矩阵a的n次幂的函数
 8 long long * Matrix(long long *a,int n)
 9 {
10 long long *result = (long long *)malloc(sizeof(long long)*4);
11 long long *finnal = (long long *)malloc(sizeof(long long)*4);
12 //如果n等于1的话,则直接返回矩阵a,毕竟,一次幂就不必求了。
13 if(n==1)
14 return a;
15 //先求出矩阵的n/2次幂
16 long long *CurMatrix = Matrix(a,n/2);
17 //两个矩阵的n/2次幂相乘得到矩阵的n次幂
18 result[0] = CurMatrix[0]*CurMatrix[0]+CurMatrix[1]*CurMatrix[2];
19 result[1] = CurMatrix[0]*CurMatrix[1]+CurMatrix[1]*CurMatrix[3];
20 result[2] = CurMatrix[2]*CurMatrix[0]+CurMatrix[3]*CurMatrix[2];
21 result[3] = CurMatrix[2]*CurMatrix[1]+CurMatrix[3]*CurMatrix[3];
22 //如果n为奇数的话,则(n/2)会少一位,补回来。a = a^(n/2)*a^(n/2) * a;
23 if(n%2==1)
24 {
25 finnal[0] = result[0]*a[0]+result[1]*a[2];
26 finnal[1] = result[0]*a[1]+result[1]*a[3];
27 finnal[2] = result[2]*a[0]+result[3]*a[2];
28 finnal[3] = result[2]*a[1]+result[3]*a[3];
29 }
30 //如果n为偶数的话,n/2还是n/2
31 else
32 finnal = result;
33 return finnal;
34 }
35
36 int main(void)
37 {
38 long long a[4];
39 int n;
40 cin>>n;
41 //矩阵按一位数组设置,t[0]即为febonacci(n)
42 a[0] = 1;
43 a[1] = 1;
44 a[2] = 1;
45 a[3] = 0;
46 long long *t = Matrix(a,n-1);
47 cout<<t[0]<<endl;
48 return 0;
49 }

View Code

显而易见,该算法的复杂度为O(logn)。
以上三种方法的时间效率一次增高,虽然人们普遍对第三种算法中的公式比较陌生,但经过一番细细地琢磨以后,便能体会到它的独到之处。
(声明:文章版权归原作者所有,转载请注明出处:http://blog.csdn.net/mshantingting/article/details/22689573)

转载于:https://www.cnblogs.com/huashanqingzhu/p/3637518.html

斐波那契数列的低效与高效解法 【转】相关推荐

  1. (兔子繁殖问题)斐波那契数列:递归非递归解法

    题目 假设一对幼年兔子需要一个月长成成年兔子,一对成年兔子一个月后每个月都可以繁衍出一对新的幼年兔子.不考虑死亡的情况,问第 N 个月时共有多少对兔子? 这是一个典型的斐波那契数列问题,即 第一个月有 ...

  2. 斐波那契数列递归解法

    递归解斐波那契数列 斐波那契数列最直观的递归解法: int fib(int n){if (n<2) { return n;} else {return fib(n-1) + fib(n-2);} ...

  3. C语言数据结构----递归的应用(斐波拉契数列、汉诺塔、strlen的递归算法)

    本节主要说了递归的设计和算法实现,以及递归的基本例程斐波拉契数列.strlen的递归解法.汉诺塔和全排列递归算法. 一.递归的设计和实现 1.递归从实质上是一种数学的解决问题的思维,是一种分而治之的思 ...

  4. fibonacci数列前20项_面试题精选:神奇的斐波那契数列

    斐波那契数列,其最开始的几项是0.1.1.2.3.5.8.13.21.34-- ,后面的每一项是前两项之和,事实上,斐波那契在数学上有自己的严格递归定义. f0 = 0 f1 = 1 f(n) = f ...

  5. 斐波那契数列c++代码_轮到你了,斐波那契数列!

    前阵子,日剧"轮到你了"终于大结局了,虽然结局有点一言难尽,但黑岛和二阶堂两个学霸之间的爱情,还是很甜呢呐!两个学霸之间的默契的斐波那契数列也被许多网友认为是凶手行凶的依据.到底这 ...

  6. 【README2】动态规划之斐波那契数列说明重叠子问题如何解决

    接上文:[README1]动态规划之解题思路 文章目录 斐波那契数列讲解--解决重叠子问题 (1)暴力递归 (2)带有备忘录的递归解法 (3)自底向上--dp数组解法 (4)总结:状态转移方程 (5) ...

  7. 斐波那契数列(Fibonacci sequence)【思路及实现】

    定义 斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数列 ...

  8. 三种方法详解斐波那契数列

    本文同步.md文件,在展示上会有些许问题 原始版本在语雀平台.请各位移步查阅. 代码保存在码云平台供有需要者下载阅览. 本文采用暴力递归,带备忘录的递归,以及动态规划求解斐波那契数列.不到之处,欢迎指 ...

  9. java 斐波拉_Java实现斐波那契数列

    斐波纳契数列,又称黄金分割数列,指的是这样一个数列:1.1.2.3.5.8.13.21.--在数学上,斐波纳契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=F(n-1)+F(n-2)(n&g ...

最新文章

  1. 宁波大红鹰学院计算机毕设,网络文化对价值观的影响调查报告马克思主义基本原理概论》课程调查实践报告大学毕业设计.doc...
  2. MyBatisPlus中进行通用CRUD全局策略配置
  3. nginx 中location中root和alias的区别
  4. java 请求http get_java http get/post请求
  5. 前端学习(2967):实现路由跳转的方式
  6. 最良心不过AMD AM4接口下一代可继续用
  7. 走进Linq-Linq to SQL感性认识篇
  8. 用pygame实现打飞机游戏-2-检测键盘
  9. Atitit codeblock c++开发环境建立attilax总结
  10. Linux-Anaconda-pycharm 安装 配置
  11. java实现pdf转word
  12. java cmyk转rgb_图片 CMYK转RGB 代码
  13. html5饼图的制作方法,excel2010复合饼图制作方法
  14. 服务器ajax无响应时间,ajax 服务器响应时间
  15. python之selenium设置浏览器为手机模式(开发者模式)
  16. ipa在线安装搭建_五大在线苹果企业签名平台评测:微导流居然打败了蒲公英
  17. android 进制转换的方法
  18. linux 下简单安装 pathogen.vim
  19. 四信LoRa模组F8L10D率先通过CLAA COMPATIBLE认证
  20. CF1485C(整除分块+根号分块)

热门文章

  1. C#数据结构与算法揭秘17
  2. VM与VPC共存(续)
  3. 俞敏洪在北大2008年开学典礼上的演讲
  4. java 反射 ppt_Java反射的基本使用
  5. 数据结构源码笔记(C语言):二叉排序树的基本操作算法
  6. 计算机网络管理考试价格,2021年计算机网络管理员考试模拟试题库和答案...doc...
  7. 线程的状态 Thread.State||NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED
  8. Express 的简单使用
  9. Hello World探究
  10. VS 2012 NuGet错误