目录

  • 题目描述
  • 1、暴力递归法的重叠子问题
  • 2、备忘录解法
  • 3、dp数组迭代算法
  • 4、滚动数组优化
  • 5、参考链接

题目描述

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:

F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

1、暴力递归法的重叠子问题

暴力递归法最为常见,但是同时它的时间复杂度也是最高的,附带了许多重复计算。

class Solution {public:int fib(int n) {if(n==0) return 0;else if(n == 1 || n == 2) return 1;else return (fib(n - 1) + fib(n - 2))%1000000007;}
};

画出递归树:

算法时间复杂度为递归二叉树结点总数,为O(2^n)。f(18)、f(17)被重复计算了,并且以f(18)为根节点的递归树体积也是十分巨大的,如果再算一遍会耗费大量的时间。
这个问题性质我们可以描述为“重叠子问题”。

2、备忘录解法

既然是重复计算的问题,我们就可以构造一个备忘录。
每次计算出某个子问题的答案先别着急返回,先记到备忘录中再返回;
每次遇到一个子问题,先去备忘录中查找,如果已经解决了这个问题,就直接把答案拿过来用,不再进行计算。

class Solution {public:int search_helperTab(vector<int >& helperTab,int n){//n较小的直接返回if(n == 1 || n == 2) return 1;//如果已经计算过了,直接返回计算过的值if(helperTab[n] != 0) return helperTab[n];//如果没有计算过,则需要重新计算一遍else{helperTab[n] = (search_helperTab(helperTab,n-1) + search_helperTab(helperTab,n-2))%1000000007;}return helperTab[n];}int fib(int n) {if(n==0) return 0;//构建一个备忘录vector<int >helperTab(n+1,0);return search_helperTab(helperTab,n);}
};

带备忘录的递归算法,将一颗存在巨量冗余的递归树剪枝为没有冗余的递归图。
递归算法时间复杂度=子问题个数 * 解决子问题所需要的时间。
由于不存在冗余计算,所以子问题个数为O(n);解决一个子问题的时间是O(1);
所以本算法的时间复杂度是O(n)。
注意,我们刚刚画的递归树是从上向下延伸的,都是从一个规模较大的原问题,向下逐渐分解规模,直到触底(f(1)、f(2)),然后逐层返回答案,这就是自顶向下。

如果直接从最底下的最小规模的f(1)、f(2)开始往上推导,直到f(20),这就是动态规划的思路。

3、dp数组迭代算法

class Solution {public:int fib(int n) {if(n==0) return 0;if(n == 1 || n == 2) return 1;//构建一个备忘录vector<int >dp(n+1,0);dp[1]=dp[2]=1;for(int i = 3;i <= n;i++)dp[i]=(dp[i-1]+dp[i-2])%1000000007;return dp[n];}
};

4、滚动数组优化

状态方程中的当前状态只由前两个状态决定,所以不需要一个数组进行存放。

class Solution {public:int fib(int n) {if(n==0) return 0;if(n == 1 || n == 2) return 1;int pre=1,curr=1;for(int i = 3;i <= n;i++){int sum=(pre+curr)%1000000007;pre=curr;curr=sum;}return curr;}
};

这样空间复杂度就降到O(1)了。

5、参考链接

剑指 Offer 10- I. 斐波那契数列
labuladong:动态规划详解(修订版)

剑指 Offer 10- I. 斐波那契数列 (从重叠子问题到备忘录到dp数组迭代解法)相关推荐

  1. 剑指offer Q10 -I 斐波那契数列

    思路 本题看起来是简单题,但是实际上对性能和结果都有要求 直接使用递归写法性能上是不能通过的.只能使用迭代写法,通过两个变量re1和re2来保存前一步和前前一步的结果,最后返回re2即可.但是注意,本 ...

  2. 剑指Offer_入门_JZZ_斐波那契数列

    剑指Offer_入门_JZZ_斐波那契数列 题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1).n≤39. 示例1 输入4,返回 ...

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

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

  4. 剑指offer——面试题10:斐波那契数列

    个人答案: 1 #include"iostream" 2 #include"stdio.h" 3 #include"string.h" 4 ...

  5. 【斐波那契数列】10题-斐波那契数列

    1 题目描述 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项.斐波那契数列的定义如下: F(0) = 0, F(1) = 1 F(N) = F(N - 1) + F(N - ...

  6. c语言斐波那契数列前20项和,,c语言利用数组求斐波那契数列的前20项

    推荐回答 一.斐波那契数列指的是这样一个数列1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711 ...

  7. 【剑指offer】10A--求裴波那切数列的第n项,C++实现

    #本文是牛客网<剑指offer>刷题笔记 1.题目 写入一个函数,输入n,输出裴波那切数列的第n项 2.思路 递归--时间和空间复杂度高 循环--时间和空间复杂度低,通过循环迭代计算第n项 ...

  8. 面试题10:斐波那契数列

    斐波那契数指的是这样一个数列:0.1.1.2.3.5.8.13.21.-- 这个数列从第三个数开始,之后的每一个数都由它前的两数相加得到. 我们知道在编程中我们可以用递归和迭代两种方法求指定的斐波那契 ...

  9. 剑指offer Leetcode 10 I .斐波那契数列

    解法1:效率低的解法 复杂度 速度十分缓慢,重复计算太多 代码 //未考虑溢出和取模 class Solution {public:int fib(int n) {if(n <= 0)retur ...

最新文章

  1. 全面综述:图像特征提取与匹配技术
  2. Tomcat服务器server.xml详解
  3. tomcat配置与应用(2)
  4. 云计算数据中心建设热潮的两个图表
  5. 正则表达式变量名命名的规则_如何简单有效地提高代码质量?修改变量名即可...
  6. 一台机器起多个filebeat_全自动多色丝印机一台多少钱?
  7. mysql index sub part_mysql中的key和index 理解
  8. qt最大化和还原实现_从高被引研究论文来看电催化CO2还原研究进展
  9. vue保存页面的值_vue前端页面跳转参数传递及存储
  10. nginx每日日志切割脚本
  11. 如何拷贝工程_如何获得微信小游戏跳一跳源码以及源代码组合包括哪些
  12. [转载]JUnit3 与 JUnit4 的区别
  13. MySQL-快速入门(7)索引
  14. 企业网站建设流程步骤,教你快速建网站
  15. 学期学会的一些代码23333原创
  16. 2、51单片机——I2C 总线
  17. Pipeline并行处理模型
  18. 这个案例你可以直接拿去用。
  19. Ubuntu 2004 鼠标可以移动但是点击无响应 排查流程
  20. 最终幻想X-2国际版+最终任务

热门文章

  1. 【JavaScript高级教程】JavaScript prototype(原型对象)
  2. 数据类型转换为false的有哪些?
  3. 教你玩转CSS 精灵图/雪碧图
  4. python合并数组输出重复项_python - 不同数组项的所有可能组合[重复] - 堆栈内存溢出...
  5. 漏洞工具:nmap和nessus
  6. comcerter无法识别串口_基于FPGA 的MXN维字符识别的实现
  7. android finish 区别,Android Activity类finish、onDestory和System.exit介绍
  8. 为什么要使用Vuex?
  9. DIV CSS浏览器的兼容性
  10. 课时67.标签选择器(掌握)