斐波那契数列数列相关简化1

news2024/12/25 13:05:44

斐波那契数列问题介绍:

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=1,F(1)=1, F(n)=F(n - 1)+F(n - 2)(≥ 2,∈ N*)在现代物理、准晶体结构、化学等领域,斐波那契数列都有直接的应用,为此,美国数学会从 1963 年起出版了以《斐波那契数列季刊》为名的一份数学杂志,用于专门刊载这方面的研究成果。

第一、第二项都是1,从第三项开始F(n)=F(n - 1)+F(n - 2),这个使用递归很容易求解:

几行代码就能解决:

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

对斐波那契数列的求解我们有以下的思考:

1)斐波那契数列的线性求解(O(N))的方式非常好理解

2)同时利用线性代数,也可以改写出另一种表示

 | F(N) , F(N-1) | = | F(2), F(1) |  *  某个二阶矩阵的N-2次方

//|f(3) f(2)| = |f(2) f(1)| * base
//|f(4) f(3)| = |f(3) f(2)| * base
//|f(4) f(3)| = |f(2) f(1)| * base的平方

3)求出这个二阶矩阵,进而最快求出这个二阶矩阵的N-2次方

//因为f(n)肯定是一个整数,而原来的|f(2) f(1)|是一行两列,所以base是2行(要与|f(2) f(1)|的列数相同),有因为结果是一行两列
//所以base的列数也是2,我们假设矩阵是{{a,b},{c,d}}
//|2 1| = |1 1| * base得出 1*a + 1 * c = 2  1 * b+ 1 *d = 1
//|3 2| =  |2 1| * base得出 2*a+1*c=3 2*b+1*d=2,两个推出a = 1, b = 1, c =1 ,d=0
//所以求解出base矩阵是{{1,1},{1,0}}

怎么去求矩阵的n次方呢?我们先看某个数的n次方,比如10的75次方,但是10*10*10...10乘75次的话,那不还是O(N)的时间复杂度吗,这里有别的路径75=64+8+2+1, ,那怎么快速的得到1,2,8,64次方呢,10 本身是10的1次方 10*10(a)就是10的2次方,a*a(b)就是10的四次方, b*b(c)就是10的8次方,c*c(d)就是10的16次方,d*d(e)就是10的32, e*e(f)就是10的64次方,我们一共算了6次,加上10本身也就顶多7次,接近O(longN)。75对应的二进制数是 ....1001011只要把二进制中1,2,8,64所代表的1乘入当前结果就可以了

这种解法的时间复杂度就变成了O(logN)

下面上代码,依然有非常详细的注释:

package dataStructure.fibonacci;

import static dataStructure.danDiaoZhan.SumOfSubarrayMinimums.printArr;

public class FibonacciStandard {
    public static int fib(int n) {
        if( n == 0) return 0;
        if(n <= 2) return 1;
        return fib(n - 1) + fib(n-2);
    }

    public static int fib2(int n) {
        if(n == 0) return 0;
        if(n <= 2) return 1;
        //大于2的时候f(n) = f(n-1) + f(n-2)是稳定的递推结构,有稳定的位置依赖,可以使用矩阵求解
        //|f(3) f(2)| = |f(2) f(1)| * base
        //|f(4) f(3)| = |f(3) f(2)| * base
        //|f(4) f(3)| = |f(2) f(1)| * base的平方
        //
        //因为f(n)肯定是一个整数,而原来的|f(2) f(1)|是一行两列,所以base是2行(要与|f(2) f(1)|的列数相同),有因为结果是一行两列
        //所以base的列数也是2,我们假设矩阵是{{a,b},{c,d}}
        //|2 1| = |1 1| * base得出 1*a + 1 * c = 2  1 * b+ 1 *d = 1
        //|3 2| =  |2 1| * base得出 2*a+1*c=3 2*b+1*d=2,两个推出a = 1, b = 1, c =1 ,d=0
        //所以求解出base矩阵是{{1,1},{1,0}}
        int[][] base = {{1,1},{1,0}};
        //|f(n) f(n - 1)| = |f(2) f(1)| * base的n-2次方
        //先计算base的n-2次方
        int[][] matrix = matrixPower(base, n-2);
        //|f(2) f(1)|是{{1,1}}
        int[][] matrix21 = {{1,1}};
        //计算|f(2) f(1)|乘以base的n-2次方
        matrix = product(matrix21, matrix);
        //返回的结果只有一行{{f(n) f(n-1)}}
        //[0][0]就是f(n)
        return matrix[0][0];
    }

    public static int[][] matrixPower(int[][] m, int p) {
        int[][] res = new int[m.length][m.length];
        //先构建单位矩阵,也就是m的0次方
        for(int i = 0; i < res.length; i++) {
            res[i][i] = 1;
        }
        //矩阵的1次方,这里是为了在不改变m的情况下使用它的平方,4次方,8次方。。。64次方
        int[][] t = m;
        for(;p != 0; p >>= 1) {
            //最右侧是不是1,用完之后右移一位相当于比较上一位
            //拿个数字举例子,75=64+8+2+1,分别是从右往左第7,4,2,1位是1,也就是...1001011
            //分别是t * t^2 * t^8 * t^64
            //t是刚开始进循环的时候t^2是第二次进来的时候,t^8是第四次进来的时候,t^64是第7次进来的时候
            //也就是我们对于75只用了7次,基本是log(N)的级别
            if((p & 1) != 0) {
                res = product(res, t);
            }
            //每次自己变自己的平方依次求2,4,8,16,32,64次方
            t = product(t,t);
        }
        return res;
    }

    public static void main(String[] args) {
        int result = fib(7);
        System.out.println(result);

        int[][] matrix1 = {{2,1}};
        int[][] matrix2 = {{1,1}, {1,0}};
        int[][] matrix = product(matrix1, matrix2);
        if(matrix != null)
        printArr(matrix);

        int n = 7;
        int resultn = fib2(n);
        System.out.println(resultn);
    }

    public static int[][] product(int[][] matrix1, int[][] matrix2) {
        //第一个矩阵的行要和第二个矩阵的列相等
        if(matrix1 == null || matrix2 == null || matrix1[0] == null || matrix2[0] == null || matrix1[0].length != matrix2.length) {
            return null;
        }
        //第一个矩阵的行数
        int n = matrix1.length;
        //第二个矩阵的列数
        int m = matrix2[0].length;
        //第一个矩阵的列数也是第二个矩阵的行数,用于循环里面的计算项
        int k = matrix1[0].length;
        int[][] matrix = new int[n][m];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                matrix[i][j] = 0;
                for(int k1 = 0; k1 < k; k1 ++) {
                    matrix[i][j] += matrix1[i][k1] * matrix2[k1][j];
                }
            }
        }
        return matrix;
    }
}

可能想理解这个你需要复习一下大学时候线性代数的东西:矩阵的乘法

 看不懂这个分析的话可以看一下百度百科里的解释

矩阵乘法_百度百科

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/560184.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

包管理工具详解npm、yarn、cnpm、npx、pnpm

目录&#xff1a; 1 npm包管理工具 2 package配置文件 3 npm install原理 4 yarn、cnpm、npx 5 发布自己的开发包 6 pnpm使用和原理 当我们使用npm install xxxx 的时候会添加一个node_module和2个json文件&#xff1a; package.json是配置信息文件&#xff0c;  这个配…

Go完整即时通讯项目及Go的生态介绍

Go完整即时通讯项目 项目架构&#xff1a; 1 编写基本服务端-Server server.go package mainimport ("fmt""net" )// 定义服务端 type Server struct {ip stringport int }// 创建一个Server func NewServer(ip string, port int) *Server {return …

Jenkins + docker-compose 在 Centos 上搭建部署

一、前期准备 1. 检查 CentOS上 是否安装 docker 可以使用以下命令&#xff1a; sudo docker version 如果已经安装了Docker&#xff0c;它将显示有关Docker版本和构建信息的输出。如果未安装Docker&#xff0c;将收到有关命令未找到的错误消息。 2. 检查是否安装 docker-…

cookie-机制

目录 一、基础概念 二、cookie的处理方式 一、基础概念 1、cookie是存储在客户端的一组键值对 2、web中cookie的典型应用&#xff1a;免密登陆 3、cookie和爬虫之间的关联 有时&#xff0c;对一张页面进行请求的时候&#xff0c;如果请求的过程中不携带cookie的话&#xf…

Openai+Coursera: ChatGPT Prompt Engineering(四)

想和大家分享一下最近学习的Coursera和openai联合打造ChatGPT Prompt Engineering在线课程.以下是我写的关于该课程的前两篇博客&#xff1a; ChatGPT Prompt Engineering(一)ChatGPT Prompt Engineering(二)ChatGPT Prompt Engineering(三) 今天我们来学习第三部分内容&…

Java on Azure Tooling 4月更新|路线图更新及 Azure Toolkit for IntelliJ 增强

作者&#xff1a;Jialuo Gan - Program Manager, Developer Division at Microsoft 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎来到 Java on Azure 工具产品的4月更新。让我们首先来谈谈我们对未来几个月的 Java on Azure 开发工具的投资。在这次更新中&#xff0c;我们…

js - 闭包

1、闭包的概念 闭包&#xff1a;函数嵌套函数&#xff0c;内层函数访问了外层函数的局部变量。 // 闭包 function func1() {let a 9;let b 8;function func2() {console.log("a", a); // a 9}func2(); } func1(); 分析&#xff1a; 需要访问的变量会被放到闭包…

【云原生|Kubernetes】05-Pod的存储卷(Volume)

【云原生Kubernetes】05-Pod的存储卷&#xff08;Volume) 文章目录 【云原生Kubernetes】05-Pod的存储卷&#xff08;Volume)简介Volume类型解析emptyDirHostPathgcePersistentDiskNFSiscsiglusterfsceph其他volume 简介 Volume 是Pod 中能够被多个容器访问的共享目录。 Kubern…

ChatGPT可以帮助开发人员的8种方式...

“适应或灭亡”是科技界的口头禅&#xff0c;如果您是开发人员&#xff0c;则尤其如此。 由于技术的动态发展&#xff0c;开发人员面临着比大多数人更大的压力&#xff0c;他们要领先于适应和精通最好的工具。ChatGPT 是最新的此类工具。 虽然有人说 ChatGPT 是“工作杀手”&…

比Figma更丝滑的“Figma网页版“

随着互联网的全面普及和全球化&#xff0c;设计协作工具逐渐成为团队协作中不可或缺的一部分。设计师们常需要通过在线设计协作工具来完成设计任务&#xff0c;而 Figma 作为协作工具的佼佼者&#xff0c;成为了许多设计师心中的首选。但是&#xff0c;对于国内设计师来说&…

Leetcode406. 根据身高重建队列

Every day a Leetcode 题目来源&#xff1a;406. 根据身高重建队列 解法1&#xff1a;贪心 题解&#xff1a;根据身高重建队列 我们先按照身高从大到小排序&#xff08;身高相同的情况下K小的在前面&#xff09;&#xff0c;这样的话&#xff0c;无论哪个人的身高都小于等于…

kubeadm安装集群的时候kube-proxy是如何安装的

背景 最近升级k8s集群时遇到这个问题&#xff0c;集群是使用kuberadm自动化脚本安装的&#xff0c;之前一直认为kubeadm安装的集群这些组件除了kubelet都是静态pod跑起来的。 其实kube-proxy并不是. kube-proxy是如何安装的 在使用kubeadmin安装Kubernetes集群时&#xff0c…

Echarts通过Jquery添加下拉列表动态改变展示的数据和图表

前言 在项目中&#xff0c;有时候我们会一些需求&#xff0c;比如要用Echarts绘制一个饼状图&#xff0c;并且要设置一个下拉列表&#xff0c;当我点击某个选项的时候&#xff0c;饼状图里面的数据会改变&#xff0c;图表样式也会发生改变。我们可以配合Jquery来实现这个功能。…

数字电路基础

目录 一、不同进制之间的转换 二、逻辑代数基础 三、门电路 四、组合逻辑电路 五、半导体存储电路 六、时序电路 一、不同进制之间的转换 二-十转换&#xff1a; 十-二转换&#xff1a; 二-十六转换 十六-二转换 八-二转换 二-八转换 十六-十转换&#xff1a; 先转换成…

python绘制气泡图|随机生成数据

python绘图系列文章目录 往期python绘图合集: python绘制简单的折线图 python读取excel中数据并绘制多子图多组图在一张画布上 python绘制带误差棒的柱状图 python绘制多子图并单独显示 python读取excel数据并绘制多y轴图像 python绘制柱状图并美化|不同颜色填充柱子 python随机…

log4cpp的使用

log4cpp的使用逻辑构造基本模板布局的格式化目的地对象操作文件回卷文件 log4cpp的使用 逻辑构造 目的地Appender&#xff1a;用于表示日志系统最后输出到哪 布局Layout&#xff1a;表示你输出的格式&#xff0c;类似与printf 优先级Priority&#xff1a;常见的优先级有emerg&…

【WSN覆盖】基于麻雀搜索算法的三维无线传感器网络覆盖优化 三维WSN覆盖优化【Matlab代码#26】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取】1. SSA算法2. 三维覆盖模型3. 部分代码展示4. 仿真结果展示5. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取】 1. SSA算法 2. 三维覆盖模型 三维覆盖模…

搜狐发布Q1财报:读懂前瞻性布局背后的长期主义

5月15日&#xff0c;搜狐发布了2023年第一季度财报。财报显示&#xff0c;搜狐总收入为1.62亿美元&#xff0c;其中&#xff0c;品牌广告收入为2300万美元&#xff1b;在线游戏收入为1.29亿美元。 同时&#xff0c;归于搜狐公司的非美国通用会计准则净亏损为1300万美元。 搜狐…

ChatGPT+Mermaid Live Editor画流程图

1.粘贴代码通过gpt翻译成Mermaid代码&#xff0c;生成流程图 public int largestValsFromLabels(int[] values, int[] labels, int numWanted, int useLimit) {// 将元素按值从大到小排序PriorityQueue<int[]> pq new PriorityQueue<>((a, b) -> b[0] - a[0])…

MySQL运维篇

一.日志 1.1 错误日志 错误日志是 MySQL 中最重要的日志之一&#xff0c;它记录了当 mysqld 启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时&#xff0c;建议首先查看此日志。 错误日志是默认开启的…