• 递归
  • 动规
    • 记忆化
    • 递推
  • 快速幂

斐波那契数列,说起来大家都很熟悉,在练习编程的时候,也会经常被拿来作为例子

递归

这也是最常见的解法了,在最开始学习编程的时候,老师经常用这个例子。
因为他的定义就是递归的,用它可以显而易见地提出递归的思想,n=0和n=1 n=0 和 n = 1 作为递归基,其他的数分别递归求解 fn=fn−1+fn−2 f_n = f_{n-1} + f_{n-2}。

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

动规

但是很容易地就会发现,这个思路十分清晰的算法太慢了。因为他们中的很多值在被重复地计算,例如 f5=f4+f3f_5 = f_4+f_3, f4=f3+f2 f_4=f_3+f_2, f3f_3就被重复地计算了,重复的部分增加的非常快,一旦当 nn 大于 40 多时,就已经很难进行计算了。

这里我们可以利用动规的思想来进行计算,复杂度都能降到 O(n)O(n)。

记忆化

也是最简单的,可以先开一个数组,并且在每次计算出结果后,保存下来,就可以避免重复计算。

int f[10000];
int fib(int n)
{if(f[n]) return f[n];if(n == 0) return f[0] = 0;if(n == 0) return f[1] = 1;return f[n] = fib(n-1) + fib(n-2);
}

递推

从上面的定义方程就可以看出来,每一个值只与前面的数有关于后面的数无关,这样就可以从前往后依次计算(问题比较简单,想法太顺理成章了,动规得太不明显了,但的确是动规)

int fib(int n)
{int f[3] = { 0, 1, 1}if(n<=2) return f[n];for(int i=3; i<=n; i++){f[0] = f[1];f[1] = f[2];f[2] = f[1] + f[0];}return f[2];
}

当然平时做题时还是会开一个数组进行保存,以后查询时就是 O(1)O(1)的复杂度了。

int f[10000];
int init()
{f[0] = 0;f[1] = 1;for(int i=2; i<10000; i++) f[i] = f[i-1] + f[i-2];
}
int fib(int n)
{return f[n];
}

快速幂

上面的算法,已经达到了O(n)O(n)的复杂度,已经是非常优秀的了,但是当我们需要求解很大的答案是,例如 1000000000 之类,那么也是很耗费时间的,或者说我们需要查询的次数比较少,比较分散,那么我们浪费的空间就比较大。下面利用矩阵就是另外一种求解的方法。
利用矩阵的性质我们可以得到下面的结论

(fn+1fnfnfn−1)∗(1110)=(fn+1+fnfn+fn−1fn+1fn)(利用fib数列的定义)=(fn+2fn+1fn+1fn)

\left(\begin{matrix}f_{n+1} & f_n \\f_n & f_{n-1} \\\end{matrix}\right)*\left(\begin{matrix}1 & 1 \\1 & 0 \\\end{matrix}\right)=\left(\begin{matrix}f_{n+1}+f_n & f_{n+1} \\f_n+f_{n-1} & f_n \\\end{matrix}\right)(利用fib数列的定义)=\left(\begin{matrix}f_{n+2} & f_{n+1} \\f_{n+1} & f_n \\\end{matrix}\right)

而我们令 n=1, 则

(fn+1fnfnfn−1)=(1110)

\left(\begin{matrix}f_{n+1} & f_n \\f_n & f_{n-1} \\\end{matrix}\right)=\left(\begin{matrix}1 & 1 \\1 & 0 \\\end{matrix}\right)
综上,我们可以得出这样的结论

(fn+1fnfnfn−1)=(1110)n

\left(\begin{matrix}f_{n+1} & f_n \\f_n & f_{n-1} \\\end{matrix}\right)=\left(\begin{matrix}1 & 1 \\1 & 0 \\\end{matrix}\right)^n
理论有了,我们就可以类推数的快速幂来计算矩阵的快速幂。

// 数的快速幂
int quick_pow(int a, int n)
{int re = 1;int base = a;while(n){if(n&1) re *= base;base *= base;n >>= 1;}return n;
}

矩阵快速幂,需要自己写矩阵的乘法,然后直接套用数的快速幂的模板就行

// 矩阵快速幂struct matrix
{int data[2][2];// 矩阵乘法matrix operator*(matrix & rhs){matrix temp;for(int i=0; i<2; i++){for(int j=0; j<2; j++)temp.data[i][j] = ( data[i][0]*rhs.data[0][j] + data[i][1]*rhs.data[1][j]) % mod;}return temp;}
};int solve(int n)
{// 初始化为单位矩阵matrix re;for(int i=0; i<2; i++)for(int j=0; j<2; j++) re.data[i][j] = (i==j);matrix base;for(int i=0; i<2; i++)for(int j=0; j<2; j++) base.data[i][j] = 1;base.data[1][1] = 0;// 数的快速幂核心代码while(n){if(n&1) re = re * base;base = base * base;n >>= 1;}return re.data[0][1];
}

例题:poj3070 - Fibonacci 解题报告

斐波那契数列的几种求解方法相关推荐

  1. 斐波拉契数列的三种实现方法

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

  2. 斐波那契数列O(logn)的求解方法

    前言 是的,没错,斐波那契数列除了递推.递归算法之外,还有更加高效的求解方法,那就是矩阵运算+快速幂. 思路: 可以先利用矩阵运算的性质将通项公式变成幂次形式,然后用平方倍增(快速幂)的方法求解第 n ...

  3. “斐波那契数列”的两种算法

    "斐波那契数列"的两种算法 斐波那契数列有个规律:从第三个数开始,每个数是前两个数之和,比如: 1 1 2 3 5 8 13 21 34 55...... 现在通过两种方式(递归与 ...

  4. Python中斐波那契数列的四种写法

    在这些时候,我可以附和着笑,项目经理是决不责备的.而且项目经理见了孔乙己,也每每这样问他,引人发笑.孔乙己自己知道不能和他们谈天,便只好向新人说话.有一回对我说道,"你学过数据结构吗?&qu ...

  5. 斐波拉契数列 Java三种实现

    对于很多Java初学者来说,求解斐波拉契数列,基本上所使用的方式都是递归.对于求解斐波拉契数列来说,递归的实现方式的效率是极其低下的. 在此,我贴出三种实现(递归,迭代,动态规划): 我们先看代码的执 ...

  6. c++调用cplex求解例子_递归算法的R语言实现 (罗汉塔、九连环、斐波那契数列等问题的求解)...

    递归算法用函数来实现,通俗地说就是函数对自身的调用,求解递归问题就转化为函数的调用关系问题.函数f(n)随自变量n的增加而变化,函数的调用关系也就表现为f(n)与f(n-1)或f(n-2)关系的问题. ...

  7. 斐波那契数列的背景及解决方法

    斐波那契数列的背景及解决方法 背景: 前两天看到一道很有意思的数学题 假定你有一雄一雌一对刚出生的兔子,它们在长到一个月大小时开始交配,在第二月结束时,雌兔子产下另一对兔子,过了一个月后它们也开始繁殖 ...

  8. 斐波那契数列的四种实现

    来自:Crossin的编程教室 孔乙己自己知道不能和他们谈天,便只好向 Intern 说话.有一回对我说道,"你写过代码么?"我略略点一点头.他说,"写过代码,--我便考 ...

  9. 剑指Offer #07 斐波那契数列(四种解法)| 图文详解

    题目来源:牛客网-剑指Offer专题 题目地址:斐波那契数列 题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0).n<=39 题目解析 ...

  10. php算法求出兔子数列,PHP算法:斐波那契数列的N种算法

    前言 前段时间,遇到优化计算斐波那契数列的常规递归方法,但是一时间并没有及时想到很好的方法,所以后面查找了相关资料,总结了多种计算解法,所以分享出来,和大家一起交流学习. 斐波那契数是什么 斐波那契数 ...

最新文章

  1. [剑指offer]面试题第[28]题[Leedcode][JAVA][第101题][对称二叉树][队列][递归]
  2. linux添加video驱动,linux下video驱动源码位置
  3. ajax post json php,ajax POST json对象给PHP,PHP怎么接收值
  4. 「开源·共创·照亮」TDengine开源两周年暨灯塔计划发布会邀你一起闪耀
  5. lisp医院化验系统_医院管理系统(his)电子病历 体检系统 l is pacs
  6. 搜索引擎-应用篇(地理位置查询)
  7. 图形API的简单了解
  8. bios 刷 灵耀14_华硕灵耀Deluxe14笔记本装win10及bios设置教程(uefi+gpt)
  9. MySQL数据库删除大量数据的方式
  10. 不同手机型号图文预览_各种手机型号的查询方法(国外英文资料).doc
  11. [记录]Cloudflare之WARP及其他app的DNS测试
  12. idrac虚拟控制台的使用
  13. 基层管理者项目管理二三事
  14. 【cookie】设置cookie过期时间 超时时间,Cookie 设置 expires
  15. 第一课.极大似然估计与有偏性无偏性
  16. ElasticSearch从入门到精通--第七话(自动补全、拼音分词器、自定义分词、数据同步方案)
  17. 【ZOJ题目分类】备忘
  18. 了解一下高速动态称重产品
  19. 三坐标检测之测头系统科普
  20. web服务选择lighttpd,采用fcgi组件技术扩展处理业务层

热门文章

  1. zotero自动安装word插件失败
  2. Texmacs使用注意事项
  3. 综述:如何研究植物基因组DNA羟甲基化(5hmC)?|易基因
  4. 使用python快速插入一百万数据
  5. 一元非线性回归方程(matplotlib)
  6. 测试使用bytes.buffer()的单线程与多线程的写效率
  7. Jquery 实现json复杂查询等操作(jsonDB)
  8. 磨刀不误砍柴工(1)stress 和 pidstat
  9. 一文快速了解MaxCompute
  10. 2512厚膜贴片电阻使用介绍