求斐波那契数列的三种方法

article/2025/8/30 2:06:50

什么是斐波那契数列,1,1,2,3,5,8,13...这样一个数列就是斐波那契数列,求第n项的值。

一、经典求法

观察数列可得,除了第一项和第二项,所有的数列的值都是前一项和前一项的前一项的加和,转换成函数也就是f(n) = f(n-1) + f(n-2)

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

显然,递归n次,时间复杂度O(2^n),太恐怖,所以,必须优化。

二、顺序求法

因为斐波那契数列可以从左到右顺序的求出每一项的值,因此只需要顺序计算到n项即可,时间复杂度为O(n)的,我们可以把它看成在单链表的最后插入一个右最后一个和倒数第二个指针指向的值来决定的。

public static int f2(int n) {if(n < 1) {return 0;}else if(n == 1 || n == 2) {return 1;}int res = 1;int pre = 1;int temp = 0;for(int i = 3; i < n; i++) {temp = res;res = pre + res;pre  = temp;}return res;
}

 

三、状态矩阵相乘求法

 

这是一个时间复杂度为O(log n)的算法。因为斐波那契数列在n大于等于三的时候严格遵守递推数列f(n) = f(n-1) + f(n-2),而对于一个二阶的递推数列来说,我们可以用矩阵乘法来表示,且状态矩阵是2阶的方阵:

 

= A

 

(F(N),F(N-1))= (F(N-1),F(N-2))*A

这个矩阵是怎么得到的呢,其实回顾一下我们所学的遇到一个递推公式,如何求通项公式的问题,是不是就是构造一个等比数列啊,然后换元累加求解,举个例子,温习一下:

---------------------------------------------------------------------------------------------------------------------

 

 

 

 

使用特征方程计算:

 

 

 

可以看到,这两种方法计算的结果相同,且都是正确的,但使用特征方程求解,十分方便.使用特征方程的一个问题是,如何计算得到递推公式的特征方程,

如上图,计算一个递推公式的通项公式,只要将c1和c2的值带入r^2 = c1 * r + c2即可,然后用上述的方法求解通项公式即可.注意,上述方法仅针对

这种形式的递推公式.

原理解决,下面继续看具体求法: 

----------------------------------------------------------------------------------------------------------------------

 

把斐波那契数列的前四项F(1) = 1、F(2) = 1、F(3) = 2、F(4) = 3带进去可得状态矩阵的为:

 

当求出状态矩阵之后,当n >= 2时,原来的公式可简化为:

(F(3),F(2))= (F(2),F(1))*A = (1,1)*A

(F(4),F(3))= (F(3),F(2))*A = (1,1)*A^2

.....

(F(N),F(N-1))= (F(N-1),F(N-2))*A = (1,1) *A^(n-2)

所以其斐波那契数列n项和的问题就转化为如何用一个最快的方法求一个矩阵的N次方的问题,而求矩阵N方的问题显然能够在O(log n)时间内解决的问题,因为一个矩阵的实质其实就是一个值,假设这个数为a,如何快速的求a^75次幂的值,因为75次幂的二进制形式为1001011,那么a^75就可以写成a^64*a^8*a^2*a^1,在这过程中,我们先求出a的一次幂,再求2次幂,在根据2次幂去求4次幂以此类推,最后根据32次幂求出64次幂,即75的二进制形式共有多少位我们就使用了几次乘法,而且只乘相位上为1的位置即可。

代码实现:

//特征矩阵法//求矩阵m的p次幂的值public static int[][] matrixPower(int[][] m, int p){int [][] res = new int[m.length][m[0].length];//先把res设为单位矩阵,相当于整数中的1for (int i = 0; i < res.length; i++) {res[i][i] = 1;}//临时矩阵int [][] tmp = m;for (; p != 0; p >>= 1) {if ((p & 1) != 0) {//按位与操作,其实也就是位置为1的乘把这个矩阵乘一下res = muliMatrix(res, tmp);}//等于0 的时候我临时矩阵自己乘一下tmp = muliMatrix(tmp, tmp);}return res;}//两矩阵相乘public static int[][] muliMatrix(int[][] m1, int[][] m2) {//构造出一个m1行和m2列的矩阵(矩阵相乘规则)int [][] res = new int[m1.length][m2[0].length];//给我们要得到的矩阵的每一个元素的值进行赋值操作for(int i = 0; i < m1.length; i++) {for(int j = 0; j < m2[0].length; j++) {for(int k = 0; k < m2.length; k++) {//i,j位置元素的值就是i行元素和j行元素乘积的加和res[i][j] += m1[i][k] * m2[k][j];}}}return res;}//利用矩阵乘法求解斐波那契数列第n项的值public int f3(int n){if(n < 1) {return 0;}else if(n == 1 || n == 2) {return 1;}//状态矩阵int[][] base = {{1,1},{1,0}};//最后的结果需要求矩阵的n-2次int [][] res = matrixPower(base, n-2);return res[0][0] + res[1][0];}

 

 

 


http://chatgpt.dhexx.cn/article/k4arqM2C.shtml

相关文章

斐波那契数列

斐波那契数列来源于兔子繁殖问题&#xff0c;所以也叫兔子序列。   最开始我一直不能理解兔子问题怎么和斐波那契数列联系在一起的&#xff0c;然后画了这个图之后&#xff0c;就明白了。   第一年有一对小兔子&#xff0c;一年后成年。成年的兔子又可以生出一对小兔子&…

深入浅出总结求解菲波那切数列的五种方法

文章目录 题目思路一: 递归思路二: 递归 剪枝 (递归的优化)思路三: 动态规划思路四: 迭代 (动态规划的优化)思路五: 矩阵运算 快速幂 题目 菲波那切数列 定义 a0 0, a1 1, a2 1, an an − 1 an − 2, 求 an 是多少? 思路一: 递归 由于每一项都遵循这个公式: an an −…

图解寻址方式

注: 学习自 唐朔飞《计算机组成原理》 图自 唐朔飞《计算机组成原理》PPT整合 寻址方式 一丶指令寻址 二丶数据寻址 堆栈寻址

寻址方式一

目录 立即数、寄存器、存储器的概念 数据寻址方式 立即寻址&#xff1a; 寄存器寻址&#xff1a; 存储器寻址: 注意&#xff1a; 立即数、寄存器、存储器的概念 立即数&#xff1a;参与操作的数据本身&#xff0c;8位或16位 &#xff08;只能作为src,无法成为dst&#xf…

计算机寻址方式

一、指令寻址 1.两种方式 顺序寻址 每次寻址后 PC自动 1 &#xff1b; 跳跃寻址 当跳转到 JUP 指令时 其后的为立即数指令 &#xff0c;便跳转到对应的指令数。 数据寻址 立即寻址特征 地址村的为立即数特征 直接寻址特征 形式地址为&#xff1a; 操作数的真实地址 隐含寻…

指令格式与寻址方式

指令与指令系统 指令: 控制计算机完成某种操作的命令。 指令系统&#xff1a; 处理器所能识别的所有指令的集合。 指令的兼容性&#xff1a; 同一系列机的指令都是兼容的。 汇编语言&#xff1a; 指令助记符。 指令格式 例如&#xff1a; 寻址方式 操作数可能的来源或…

寻址方式介绍

根据指令内容确定操作数地址的过程称为寻址。完善的寻址方式可为用户组织和使用数据提供方便。 ①直接寻址&#xff1a;指令地址域中表示的是操作数地址。 ②间接寻址&#xff1a;指令地址域中表示的是操作数地址的地址即指令地址码对应的存储单元所给出的是地址A&#xff0c…

8086寻址方式

8086寻址方式 寻址方式总共有两大类: 按数据寻址 按地址寻址 1.数据寻址方式 MOV DST,SRC和数据有关的寻址方式 1.立即寻址: 操作数直接在源操作数中给出 MOV AL,45H 源操作数在指令中给出,立即数只能是源操作数 立即数的长度和DST长度一致 2.寄存器寻址 操作数放在指定的寄存…

数据寻址方式

以下例子中的寻址方式说的都是源操作数&#xff0c;因为目的操作数都用的是寄存器寻址&#xff0c;不再讨论 1.立即寻址 立即寻址是指令直接给出立即数本身作为操作数&#xff0c;立即数作为指令的一部分跟指令一起存在于代码段中&#xff0c;会被指令预取队列直接取到CPU中进…

IPv6 寻址方式简介

在计算机网络中&#xff0c;寻址模式是指在网络上托管地址的机制。IPv6 提供了多种类型的模式&#xff0c;可以通过这些模式对单个主机进行寻址。也可以同时对多个主机进行寻址或者寻址最近距离的主机。 单播寻址 在单播寻址方式中&#xff0c;IPv6 接口&#xff08;主机&…

七种寻址方式(立即寻址、寄存器寻址)

七种寻址方式(立即寻址、寄存器寻址) 一、立即寻址方式 操作数作为指令的一部分而直接写在指令中&#xff0c;这种操作数称为立即数&#xff0c;这种寻址方式也就称为立即数寻址方式。 立即数可以是8位、16位或32位&#xff0c;该数值紧跟在操作码之后。如果立即数为16位或32位…

8086寻址方式图解

目录 1&#xff1a;立即寻址 2&#xff1a;寄存器寻址 3&#xff1a;直接寻址&#xff08;存储器直接寻址&#xff09; 4&#xff1a;寄存器间接寻址&#xff08;重点&#xff09; 5&#xff1a;基址寻址&#xff08;相对寻址&#xff09; 6&#xff1a;变址寻址 &#x…

七种寻址方式

七种寻址方式&#xff08;从该处学习转载&#xff0c;感谢&#xff0c;如有侵犯&#xff0c;请联系删除&#xff09; 立即寻址 操作数作为指令的一部分而直接写在指令中&#xff0c;这种操作数称为立即数&#xff0c;这种寻址方式也就称为立即数寻址方式。 立即数寻址方式通…

十种寻址方式

寻址方式 寻址方式分为指令寻址和数据寻址。 目录 寻址方式 一、指令寻址 二、数据寻址 1.立即寻址 2.直接寻址 3.隐含寻址 4.间接寻址 5.寄存器&#xff08;直接&#xff09;寻址 6.寄存器间接寻址 7.基址寻址 8.变址寻址 9、相对寻址 10、堆栈寻址 一、指令寻…

常用的图像特征提取方法

1. 灰度特征可提取&#xff1a;灰度平均值、方差 2.纹理特征提取 MATLAB程序&#xff1a; %%%特征提取 clear all; close all; clc;Ddir(E:\my_work\长光所\云图\数据集\云样本\*.jpg); cloud_featurezeros(length(D),5);for i1:length(D)imgimread([E:\my_work\长光所\云图\…

OpenCV图像特征提取

Camera系列文章 传感器融合是将多个传感器采集的数据进行融合处理&#xff0c;以更好感知周围环境&#xff1b;这里首先介绍Camera的相关内容&#xff0c;包括摄像头及图像知识基本介绍&#xff0c;OpenCV图像识别&#xff08;特征提取&#xff0c;目标分类等&#xff09;&…

(八)特征选择与特征提取

特征选择与特征提取 一、特征的选择 1、原始特征 在描述对象的时候 模式识别中把每个对象都量化为一组特征来描述&#xff0c;构建特征空间是解决模式识别问题的第一步&#xff0c;其中通过直接测量得到的特征称为原始特征。 如&#xff1a; - 人体的各种生理指标&#xff0…

机器学习之特征提取

机器学习之特征提取 1.为什么要特征提取 原始数据常常是高维的&#xff0c;其中包含了许多冗余信息或者十分稀疏或者计算量大&#xff0c;拿原始数据来训练可行&#xff0c;但是往往直接训练是低效的。所以特征提取往往是必要的。 注&#xff1a;特征提取主要是为了解决下面三…

【机器学习】特征提取

特征提取 目标 应用DictVectorizer实现对类别特征进行数值化、离散化 应用CountVectorizer实现对文本特征进行数值化 应用TfidfVectorizer实现对文本特征进行数值化 说出两种文本特征提取的方式区别 定义 特征提取是将任意数据&#xff08;如文本或图像&#xff09;转换…

特征选择与特征抽取

特征抽取和特征选择是DimensionalityReduction&#xff08;降维&#xff09;两种方法&#xff0c;但是这两个有相同点&#xff0c;也有不同点之处&#xff1a; 1. 概念&#xff1a; 特征抽取&#xff08;Feature Extraction&#xff09;:Creatting a subset of new features by…