对于兔子问题的鼎鼎大名,相信很少有人没听过吧!为了完整性还是再说一下题目吧!

题目描述:已知一对兔子每一个月可以生一对小兔子,而一对兔子出生后.第三个月开始生小兔子假如一年内没有发生死亡,则一对兔子开始,第N个月后会有多少对?

这道题所描述的就是斐波那契数列啦!这里以一对为单位,那么,从第一个月开始,每个月总共的兔子数量就是1,1,2,3,5,8,13......可以看出前两个月为1,从第三个月开始,当月的数量为前两个月数量之和,所以可以形成公式f(n)=f(n-1)+f(n-2)(n>2)同时f(1)=1,f(2)=1。

关于这道题的实现由很多种方法,那么接下来笔者就从O(2^n)说起。

1.时间复杂度O(2^n)

#include<iostream>
using namespace std;
int Fibonacci(int fib)
{if(fib<=0){return 0;}else if(fib==1||fib==2){return 1;}else{return Fibonacci(fib-1)+Fibonacci(fib-2);//当前月等于前一个月的数量加上前两个月的数量}
}
int main()
{int num,result;cin>>num;//输入第几个月result=Fibonacci(num);cout<<result;return 0;
}

那为什么说此方法的时间复杂度是O (2^n)呢?

下图描述了整个递归过程,可以看出最终形成了类似一个二叉树,每个节点都有访问,那么时间复杂度,就明显看的出来了

上图也同样暴露出上述递归算法的问题所在,就是同一个数多次访问,明明其它地方计算过了,却还会重复计算。

接下讲述另一种方法,时间复杂度有较大改善

2.时间复杂度O(n)

#include<iostream>
using namespace std;
int Fibonacci(int fib)
{int res=1;int pre=1;int temp=0;if(fib<=0){return 0;}else if(fib==1||fib==2){return 1;}else{for(int i=3;i<=fib;i++){temp=res+pre;pre=res;res=temp;}return res;}
}
int main()
{int num,result;cin>>num;//输入第几个月result=Fibonacci(num);cout<<result;return 0;
}

很明显可以看出整个时间消耗在i 在3  - fib 的循环中,时间复杂度O(n),自此斐波那契数列已经达到线性,那么,时间复杂度有没有可能更小呢?

答案是肯定的。

3.时间复杂度O(log(n)) (本方法学习自牛客网,左程云(左神))

当然在讲述这种方法之前,必须要介绍一下线性代数的知识,在线性代数中下图中的等式是恒成立的。

具体怎么证明,直接说,不会,但是这个公式确实整个算法的核心,由上面的公式我们可以列出如下图的公式并且得出a,b,c,d的值。
那么,下图所示的推导过程也就很容易理解了
现在想求F(n)整个问题就变成了一个矩阵的(n-2)次方了,那么一个矩阵的(n-2) 次,实现起来怎么达到 O(log(n))?
以下引用左神原话:
而求矩阵N次⽅方的问题,明显是一个更够在O(logN)时间内解决的问题。为了表述方便,我们现在用求一个整数N次方的例子来说明,因为只要理解了如何在O(logN)的时间复杂度内求整数N次方的问题,对于求矩阵N次方的问题是同理的,区别是矩阵乘法和整数乘法在细节上有些不一样,但是对于怎么乘更快,两者的道理相同。
假设一个整数是10,如何最快的求解10的75次方。
1,75的二进制形式为1001011。
2,10的75次方=(10^64) * (10^8) * (10^2) * (10^1)。在这个过程中,我们先求出10^1,然后根据10^1求出10^2,再根据10^2求出10^4,...,最后根据10^32求出10^64次方,即75的二进制形式总共有多少位,我们就使用了几次乘法。
3,在步骤2进行的过程中,把应该累乘的值乘起来即可。10^64、10^8、10^2、10^1应该累乘起来,因为64、8、2、1对应到75的二进制中,相应的位上是1。而10^32、10^16、10^4不应该累乘,因为32、16、4对应到75的二进制中,相应的位上是0。
整体程序实现如下:
#include<iostream>
using namespace std;
int base[4] = { 1, 1, 1, 0 };
int result[4] = { 1, 0, 0, 1 };//将结果矩阵初始为单位阵Evoid MatrixMulti(int ba[4], int re[4], bool flag)// 这个函数实现其实应该用二维数组,原谅我这一生放纵不羁爱偷懒
{int temp[4] = { 0 };temp[0] = ba[0] * re[0] + ba[1] * re[2];temp[1] = ba[0] * re[2] + ba[1] * re[3];temp[2] = ba[2] * re[0] + ba[3] * re[2];temp[3] = ba[2] * re[1] + ba[3] * re[3];if (flag){for (int i = 0; i < 4; i++){result[i] = temp[i];}}else{for (int i = 0; i < 4; i++){base[i] = temp[i];}}
}
int main()
{int month;cin >> month;if (month < 1){cout << 0 << endl;return 0;}if (month == 1||month==2){cout << 1 << endl;return 0;}month-=2;for (; month != 0; month >>= 1)//此for循环是实现O(log(n))的关键{if (month & 1){MatrixMulti(base, result,true);}MatrixMulti(base, base,false);}cout << result[0] + result[2];return 0;
}

那么到这就完了么,时间复杂度还能不能再降低呢?答案是,能。


4.时间复杂度O(1) 
之所以能实现O(1) 请感谢数学的伟大吧,竟然有人计算出了斐波那契数列的通项公式 
那么时间复杂度必须是O(1)啊!先不着急程序实现,我们想想,如果问我们怎么判断一个数是不是斐波那契数呢?同样也有 O(1)的解法:判断一个数是否是一个斐波那契数当且仅当5N^2+4或5N^2-4是平方数。我只能再一次感叹数学的伟大,所以数学系的经常来抢计算机的饭碗,我们却无能为力啊!下面给出代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
void main()
{double n;scanf("%lf",&n);printf("%d\n", (int)((pow(((1 + sqrt(5)) / 2), n) - pow(((1 - sqrt(5)) / 2), n)) / sqrt(5)));return 0;
}

结语:看见最后这几行代码我想会有很多人哭晕在厕所吧!我先哭一会!!!

兔子问题---细说斐波那契数列相关推荐

  1. 兔子繁殖问题 斐波那契数列 java实现

    兔子繁殖问题 斐波那契数列 java实现 问题描述 一对兔子,从出生后第3个月起每个月都生一对兔子. 小兔子长到第3个月开始每个月又生一对兔子. 假如兔子都不死, 请问第1个月出生的一对兔子,第n个月 ...

  2. 兔子问题,斐波纳契数列

    题目:古典问题(斐波纳契数列):有一对兔子,从出生后3个月起每个月都生一对兔子,小兔子长到第三个月又会生一对兔子,假如兔子都不死,问每个月兔子总数? 分析规律:1 1 2 3 5 8 13 21- 从 ...

  3. JavaScript算法(实例八)递归计算每个月的兔子总数【斐波那契数列】

    古典问题:有一只兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子,假如兔子都不死,问每个月的兔子总数为多少? 思考这道题的时候,如果你简单的推算一下,会发现每个月的兔 ...

  4. matlab兔子繁殖问题,斐波那契数列在《疯狂动物城》兔子繁衍中的应用

    摘    要: 计算思维的构建有助于帮助学生将实际问题转换为透明易懂的框架算法, 并借助计算机解决.以电影<疯狂动物城>中的兔子繁殖问题为例, 引出斐波那契数列, 引导学生将数学表达式转化 ...

  5. 兔子问题与斐波那契数列

    #题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子, #假如兔子都不死,问每个月的兔子总数为多少? #通过数学分析我们知道,兔子的规律为数列1, ...

  6. 神奇的兔子序列(斐波那契数列)

    14天阅读挑战赛 神奇的兔子序列 假设第1个月有1对刚诞生的兔子,第2个月进入成熟期,第3个月开始生育兔子,而1对成熟的兔子每月会生1对兔子,兔子永不死去.那么,由1对初生兔子开始,12个月后会有多少 ...

  7. JavaScript初级玩法(3)—兔子问题(斐波那契数列)

    问题 有人想知道一年内一对兔子可繁殖成多少对,便筑了一道围墙把一对兔子关在里面.已知一对兔子每一个月可以生一对小兔子,但是一对兔子要从出生后第三个月才开始生小兔子假如一年内没有发生死亡,则一对兔子一年 ...

  8. 【趣学算法】神奇的兔子序列(斐波那契数列)

    14天阅读挑战赛 努力是为了不平庸~ 算法学习有些时候是枯燥的,这一次,让我们先人一步,趣学算法!欢迎记录下你的那些努力时刻(算法学习知识点/算法题解/遇到的算法bug/等等),在分享的同时加深对于算 ...

  9. java递归方法编写兔子繁殖_2018-04-15 斐波那契数列(兔子繁殖数列)

    费波那契数列(兔子繁殖数列) 兔子在出生两个月后,就有繁殖能力,一对成年而有繁殖力的兔子每个月能生出一对小兔子来.假设一年以后所有兔子都不死,那么一对小兔子一年以后可以繁殖多少对兔子? 我们来分析一下 ...

最新文章

  1. c语言用switch编写运输运费,求助。。关于用switch编写简易计算器
  2. 幼儿园教师计算机教学计划,幼儿园教师教学计划
  3. ASP.NET Core on K8S深入学习(3-2)DaemonSet与Job
  4. oracle11g 导出表报EXP-00011:table不存在。
  5. ICCV 2019 Oral 端到端任意形状场景文字识别
  6. ios沙箱模式开启_【iOS】苹果IAP(内购)中沙盒账号使用注意事项
  7. 第五人格皮肤测试软件,第五人格皮肤美化软件2018
  8. 会声会影2018,带你体验不一样的光影世界!
  9. teablue数据分析_Bluetea蓝茶的品牌该如何分析,你知道吗
  10. spacemacs project设置
  11. win10更改计算机时间格式,Win10电脑锁屏的时钟格式怎么更改
  12. 合取式/合取范式/主合取范式/重言式/矛盾式 基本概念
  13. 数据库原理(2)——数据模型与概念模型
  14. Flutter安装后出现HTTP host not reachable.
  15. 养生之道——》早上刷牙干呕&&慢性烟炎
  16. stm32复位引脚NRST
  17. 桌面以及文件资源管理器无限重启的解决
  18. css样式的格式是什么,css的语法格式是什么
  19. swift之mutating关键字
  20. 《无极限之危情速递》观后感

热门文章

  1. Linux动态库加载函数dlopen源码梳理(一)
  2. 【亲测】Ubuntu16.04手动安装nvidia显卡驱动+CUDA 8.0--Acer E5-572G版
  3. Expires和 Cache- Control的作用是什么?
  4. 1.什么是供给需求交易?
  5. windows配置多个NTP服务器地址
  6. 文件标准I/O基本操作——FX乐曲时代_莫韵乐的Linux英雄传
  7. 排查计算机故障的思路,电脑:网络故障排查方法
  8. ARFoundation入门到精通 - 1.7 检测设备是否支持AR功能
  9. Pix2Pix原理解析
  10. JSON.prase()使用报错