斐波那契数列系列算法最优复杂度——时间复杂度优化到O(LogN)

对于菲薄那契系列问题的探讨很多,下面就以两个例子来分析:

  • 案例 一:
    在迷迷糊糊的大草原上,小红捡到了n根木棍,第i根木棍的长度为i, 小红现在很开心。想选出其中的三根木棍组成美丽的三角形。 但是小明想捉弄小红,想去掉一些木棍,使得小红任意选三根木棍都不能组成 三角形。 请问小明最少去掉多少根木棍呢? 给定N,返回至少去掉多少根?
    比如N=14.那么木棍的长度分别是1 2 3 4 5 6 7 8 9 10 11 12 13 14
    由于三角形条件必须满足 两边之和大于第三边
    所以我们只要保留木棍长度为 1 2 3 5 8 13的木棍。这些木棍任意组合都无法构成三角形
    观察这个数列,就是满足F(n) = F(n-1)+F(n-2) 的公式 ,这就是纯粹的斐波那契数列问题

  • 案例二(斐波那契相关的探讨,也可以优化到O(logN):
    一个农场,有一个母牛,农场通过生育技术人工授精让母牛只能生母牛而不让生公牛。母牛从第二年开 始生母牛,对于新生的牛需要等过了三年才能生母牛
    假设牛不会死,问n年后农场有多少只母牛?

第一年 :母牛A 1只
第二年: 母牛A生B 2只
第三年: 母牛A生C,A,B 3只
第四年:母牛A生D,A,B,C 4只
第五年:母牛A生E,B生F,A,B,C,D 6只
第六年:母牛A生G,B生H,C生I,A,B,C,D,E,F 9只
上面的多少只的数量满足公式 F(N) = F(N-1)+F(N-3)

对于案例一无非就是求出斐波那契数列问题了:

相信大家都对斐波那契数列已经相当的熟悉了,最多两分钟就可以写出来以下时间复杂度为O(N)的代码:

//递归实现
long long fib(int n)
{if (n =1 || n== 2){return 1;}return (fib(n - 2) + fib(n - 1));
}

但是上面的实现的时间复杂度是O(N)面试的时候是没有分的,而我想说的是优化到O(logN),那么下面就来探讨如何让时间复杂度到O(logN):
(由于编辑器实在难敲出数学特殊符号所以我拍成几张图片如下:)


下面就是实现代码:

    public static void main(String[] args) {System.out.println(fibonacci(5));System.out.println(fibonacci2(5));}/*** 普通解法时间复杂度O(N)* @param n* @return*/public static int fibonacci(int n) {if(n<1){return 0;}if(n==1|| n==2){return 1;}else{return fibonacci(n-1)+fibonacci(n-2);}}/*** 整个调用时间复杂度O(logN)* @param n* @return*/public static int fibonacci2(int n){if(n<1){return 0;}if(n==1 || n==2){return 1;}int[][] base = new int[][]{{1,1},{1,0}};int[][] res = marixPow(base,n-2);return res[0][0]+res[1][0];}private static int[][] marixPow(int[][] base, int n) {int[][] res = new int[base.length][base[0].length];for(int i=0;i<res.length;i++){res[i][i] = 1;//单位矩阵}int[][] t = base;for(;n!=0;n>>=1){if((n&1)!=0){//满足指数bit为为1情况res = multMaritx(res,t);}//基数矩阵在不断变化t = multMaritx(t,t);}return res;}/*** 虽然是三个for循环但是矩阵就是个2*2的大小有限。所以实际时间复杂度O(1)* @param t* @param t1* @return*/private static int[][] multMaritx(int[][] t, int[][] t1) {int[][] res = new int[t.length][t1[0].length];for(int i=0;i<t.length;i++){for(int j=0;j<t1[0].length;j++){for(int k=0;k<t1.length;k++){res[i][j] += t[i][k]*t1[k][j];}}}return res;}

下面来分析案例二:

由于案例二的公式是:F(N) = F(N-1)+F(N-3)
这是个3X3的矩阵,我们也可以通过带入前面几个值求出矩阵base来:

以下是案例二的实现代码最优解:O(logN):

/*** @author zhanglijie* @version 1.0* @since 1.1.0 2021/5/7 0007 20:54* 一个农场,有一个母牛,农场通过生育技术人工授精让母牛只能生母牛而不让生公牛。母牛从第二年开始生母牛,对于新生的牛需要等过了三年才能生母牛* 假设牛不会死,问n年后农场有多少只母牛?** 第一年 :母牛A                                 1只* 第二年: 母牛A生B                              2只* 第三年: 母牛A生C,A,B                        3只* 第四年:母牛A生D,A,B,C                       4只* 第五年:母牛A生E,B生F,A,B,C,D                6只* 第六年:母牛A生G,B生H,C生I,A,B,C,D,E,F      9只*                                          13*                                          19*** 公式:F(N) = F(N-1)+F(N-3)**/
public class CowHowMany {public static void main(String[] args) {int year =8;int sum = getHowManyCow(year);System.out.println(sum);}private static int getHowManyCow(int year) {if(year<=3){return  year;}int[][] base = new int[][]{{1,1,0},{0,0,1},{1,0,0}};int[][]res = martixPow(base,year-3);return 3*res[0][0]+2*res[1][0]+1*res[2][0];}private static int[][] martixPow(int[][] base, int n) {int[][] res = new int[base.length][base[0].length];for(int i=0;i<res.length;i++){res[i][i] = 1;//单位矩阵}int[][] t = base;for(;n!=0;n>>=1){if((n&1)!=0){res = multMaritx(res,t);}t = multMaritx(t,t);}return res;}private static int[][] multMaritx(int[][] t, int[][] t1) {int[][] res = new int[t.length][t1[0].length];for(int i=0;i<t.length;i++){for(int j=0;j<t1[0].length;j++){for(int k=0;k<t1.length;k++){res[i][j] += t[i][k]*t1[k][j];}}}return res;}
}

有关斐波那契套路的算法很多很多,我们在刷leetcode的时候或者在面试笔试的时候都会见到,以上是我对其的总结。

斐波那契数列系列算法最优复杂度-------O(logN)相关推荐

  1. JavaScript实现以数组形式返回斐波那契数列fibonacci算法(附完整源码)

    JavaScript实现以数组形式返回斐波那契数列fibonacci算法(附完整源码) fibonacci.js完整源代码 fibonacci.js完整源代码 export default funct ...

  2. 【斐波那契数列】算法优化笔记

    题目:斐波那契数列为:1,1,2,3,5,8-,求第n项? 初步分析 设an为斐波那契数列. a1=a2=1;(n<=2) an=a(n-1) + a(n-2);(n>=2) 本章总结 [ ...

  3. 斐波那契数列简单算法

    谈到斐波那契数列,可能是算法中经典的算法之一了.让我们先来看看斐波那契数列的由来: Fibonacci's original question: 1.Suppose that you are give ...

  4. 斐波那契数列python循环算法求解_斐波那契数列的算法实现 —— python

    斐波那契数列,简单地说,起始两项为0和1,此后的项分别为它的前两项之后. (注:据我百度发现,斐波那契数列的定义并非起始的两项为0和1,而是1和1,鉴于是转发的,在这里不对原作者的文章进行改动,因为, ...

  5. java斐波那契优化_用HashMap优化斐波那契数列 java算法

    斐波那契是第一项为0,第二项为1,以后每一项是前面两项的和的数列. 源码:Fibonacci.java public class Fibonacci{ private static int times ...

  6. 斐波那契数列快速算法详解

  7. 1123581321递归算法java_斐波那契数列的算法

    满意答案 wgeikq 2013.09.06 采纳率:53%    等级:13 已帮助:12456人 #include void Fdt(long F1,long F2,int N);//递推 voi ...

  8. 斐波拉契数列多种算法实现

    # 1. while循环 def fib1(m):n,a,b = 0,0,1while n<m:print(a)a,b = b, a+bn+=1 print("1*********** ...

  9. 经典算法(6)斐波拉契数列、兔子繁殖、跳台阶算法

    写在前面: 我是「扬帆向海」,这个昵称来源于我的名字以及女朋友的名字.我热爱技术.热爱开源.热爱编程.技术是开源的.知识是共享的. 这博客是对自己学习的一点点总结及记录,如果您对 Java.算法 感兴 ...

最新文章

  1. c++容器vector
  2. Windoes普通用户使用管理员下安装的软件
  3. idea控制台输出乱码
  4. 文字链接_新生命道目录及音频、文字链接(20200501更新)
  5. 技术人员如何"正确"的浪费时间?
  6. linux远程工具_【linux实操3.1】linux远程连接工具Secure的使用
  7. oracle rman备份spfile,RMAN备份恢复之SPFILE的恢复(一)
  8. UI设计学习软件下载的好去处
  9. SAP培训——SAP License基础
  10. ViewPager左右滑动
  11. json 插入数据_MongoDB如何一次插入多条json数据
  12. Mentor Graphics QuestaSim 2021 出现“正在运行后安装脚本...脚本:1/1”的问题
  13. 深度学习 个人理解使用余弦相似度对人脸图片识别的过程
  14. QT3D场景的快速绘制
  15. 卷积神经网络感受野的计算
  16. Can‘t reconnect until invalid transaction is rolled back
  17. 蓝桥杯2020年第十一届C/C++B组(第一次)省赛习题题解
  18. 通过java解码web前端直接预览海康威视摄像头
  19. 时空旅行[线段树分治][维护凸壳]
  20. C语言等待一秒,延时函数sleep()

热门文章

  1. 数据结构学习笔记(c语言版)
  2. QT实现一维码识别之Code128
  3. 搜狗私有化新进展:腾讯收购股权获准,后者曾被顶格处罚
  4. 基于Linux开源VOIP系统LinPhone[三]
  5. 零散知识点小结(nginx/linux/mycat/redis/douubo/zookeeper)
  6. java filetime_java-FileTime转换为字符串
  7. 刘连响:为什么看好小程序音视频在教育行业的应用?
  8. 数字图像处理-3.7混合空间增强法-骨骼图 基于opencv3.4.3的实现
  9. 工厂模式——学雷锋做好事
  10. 斯金纳的强化理论(1956)---轉