java编程 斐波拉契数列算法集锦【斐波拉契数列】【Fibonacci sequence】

news2024/11/13 11:28:48

斐波那契数列(Fibonacci sequence),又称黄金分割数列,是一个非常经典的递归问题。
斐波那契数列,这是一个广为人知的概念,在数学上定义为这样一个数列:0、1、1、2、3、5、8、13、21、34、……即数列的第一项为0,第二项为1,除了前两项数值以外,任意一项数值都是前两项数值的和。这个数列在自然科学的各个领域都有广泛的应用,如计算机科学、生物学、经济学等。
在这里插入图片描述
斐波那契数列是一个经典的数学问题,这个数列的神奇之处,在于它能够以惊人的方式反映自然界的许多现象。
在这里插入图片描述

用数学语言表达,斐波那契数列(F(n))可以通过递归公式定义:(F(0)=0, F(1)=1), 对于(n > 1), 有(F(n) = F(n-1) + F(n-2))。
斐波那契数列,通过Java实现可以帮助我们深入理解其原理和应用。在实际应用中,我们应根据具体情况选择合适的实现方式,以达到最优的效果。

在Java中,我们可以有很多种实现方法,效率也各不相同。如使用递归或迭代的方式来实现斐波那契数列等等。

下面,我将演绎各种各样的五花八门的斐波那契数列实现算法。

  1. 算法1: 首先给出一个斐波那契数列的递归算法版本

斐波那契数列递归公式: f(n) = f(n-1) + f(n-2)
斐波那契数列递归终结点:f(0)=0,f(1)=1;当n=2时,f(2) = f(1) + f(0) = 1
斐波那契数列的递归方向:n -> 2 (n ≥ 2,n ∈ N*)

在这里插入图片描述

Java实现的算法源码如下:

package fibonacci;
/***
 * @author QiuGen
 * @description  斐波那契数列的递归算法
 * @date 2024/8/18
 * ***/
import java.util.Map;
import java.util.TreeMap;
public class FibonacciA {
	/***斐波那契数列的递归算法,效率低下,每次递归重复计算较小的值***/
	public static long fib( int n) { 
		if (n==0) return 0;
		if (n==1) return 1;
		return fib(n-1) + fib(n-2);
	}
	
	public static void main(String[] args) {
		System.out.println("***效率低下的递归算法***");
		Map<Integer,Long> map = new TreeMap<>();
		for (int i = 0; i < 20; i++) {
			map.put(i, fib(i));
		}
		map.forEach((k,v)->System.out.println(v));
	}
}

这个递归算法最直观最简明,但非常耗时,非常耗计算机资源,如计算第六项数值时fib(5)的计算过程如下:

fib(5)
fib(4) + fib(3)
(fib(3) + fib(2)) + (fib(2) + fib(1))
((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
(((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
由此可见,这个算法在计算后面的项时需要多次重复计算前面所有的项,因此不是一种高效的算法。实际上,该算法的运算时间是呈指数级增长的;而且对计算机的内存资源也是呈指数级增长的,很容易导致计算机资源不足。
复杂度: 时间复杂度是0(n^2),空间复杂度是0(n);
程序运行结果(斐波那契数列前20项的值):
在这里插入图片描述

  1. 算法2: 斐波那契数列的优化后的递归算法版本。
    斐波那契数列的优化后的递归算法版本。
    斐波那契数列递归公式: f(n) = f(n-1) + f(n-2)
    斐波那契数列的递归终结点: 自f(0)=0,f(1)=1,递归计算至f(n)。
    斐波那契数列的递归方向:0 -> n (n ≥ 0,n ∈ N*)

这个递归算法不是很简明,有点不太好理解。算法源代码如下:

package fibonacci;
/***
 * @author QiuGen
 * @description  斐波那契数列的优化的递归算法FibonacciB
 * @date 2024/8/18
 * ***/
public class FibonacciB {
	static long getFibItem(int index)
	{
		return getFibItem(0, 1, 0, index);
	}

	static long getFibItem(long curr, long next, int currIndex, int index)
	{
		if (currIndex == index)
		{
			return curr;
		}
		else
		{
			return getFibItem(next, curr + next, currIndex + 1, index);
		}
	}

	public static void main(String[] args) {
		for (int i = 0; i < 20; i++) { //计算前20项
			System.out.println(getFibItem(i));
		}
	}
}
  1. 算法3: 斐波那契数列的优化后的尾递归算法版本。
    斐波那契数列的优化后的尾递归算法版本。
    斐波那契数列递归公式: f(n) = f(n-1) + f(n-2)
    斐波那契数列的递归终结点: 自f(0)=0 或 f(1)=1。
    斐波那契数列的递归方向:n -> 1 (n ≥ 0,n ∈ N*)

这个尾递归算法的效率比较高。
空间复杂度: 递归的深度为0(n),但是由于是尾递归,优化后的空间复杂度是0(1)
时间复杂度: 时间复杂度是0(n)

package fibonacci;
/***
 * @author QiuGen
 * @description 斐波那契数列的尾递归算法FibonacciC
 * @date 2024/8/18
 * ***/
public class FibonacciC {
    public static long fib(int index) {
        return fib(0,1,index);
    }
 
    public static long fib( long n1,long n2,int index) {
        if(index == 0) {
            return n1;
        }
        if(index == 1) {
            return n2;
        }
        return fib(n2,n1+n2,index - 1);
    }
    
    public static void main(String[] args) {
		for (int i = 0; i < 20; i++) { //计算前20项
			System.out.println(fib(i));
		}
	}
}

  1. 算法4: 借助一个数组列表ArrayList,前两项是0和1,从n=2项起,每一项是之前两项之和。实际上也是一种迭代算法。
    用Java实现斐波那契数列,最容易想到的方式,是用一个数组列表ArrayList,首两项是0和1,从n=2项起,每一项是之前两项之和,循环依次赋值。这个算法的效率还是可以的。
package fibonacci;
/***
 * @author QiuGen
 * @description  斐波那契数列的利用列表的算法
 * @date 2024/8/18
 * ***/
import java.util.ArrayList;
public class FibonacciList {
	static ArrayList<Long> list = new ArrayList<>();
	public static void fib( int n) { 
		list.add (list.get(n-1) + list.get(n-2) );
	}
	
	public static void main(String[] args) {
		//赋前两项斐波那契数列的初值
		list.add(0L);
		list.add(1L);
		for (int i = 2; i < 20; i++) { //计算前20项
			fib(i); //计算第i项值
		}
		list.forEach(System.out::println);
	}
}
  1. 算法5: 借助一个数组列表ArrayList,另一种迭代算法版本。
    下面是利用数组列表和迭代算法的版本,效率更高一点。
package fibonacci;
/***
 * @author QiuGen
 * @description  斐波那契数列利用列表的迭代算法
 * @date 2024/8/18
 * ***/
import java.util.ArrayList;
public class FibonacciIterate {
	static ArrayList<Long> list = new ArrayList<>();
	//计算前n项
    public static void fibonacciIterate(int n) {  
        long a = 0L;  
        long b = 1L; 
        long c = 0L;
        for (int i = 0; i < n; i++) { 
        	if ( i == 0) {
        		list.add(a);
			} else if ( i == 1) {
            	list.add(b);
			}
            if (i < 2)   continue;
            c = a + b;  
            list.add(c);  
            a = b;  
            b = c;  
        }  
    } 
    
    public static void main(String[] args) {
    	//计算前20项
    	fibonacciIterate(20);//计算前20项
    	list.forEach(System.out::println);
	}
}
  1. 算法6: 斐波那契数列的利用矩阵乘法、快速幂的算法版本。

运算原理:
在这里插入图片描述
我们目测计算一下。上面第一个公式,相乘后可得等式左边是向量(Fn+1,Fn),右边也是一个向量((Fn+Fn-1),Fn)。很明显是正确的,相等的,因为,相当于两个等式:Fn+1=(Fn+Fn-1)和Fn=Fn。
当n=1时,第二个公式,计算结果是 F2=1,F1=1。
当n=0时,第二个公式,矩阵的0次幂是等于单位矩阵,因此可得计算结果F1=1,F0 = 0。非常正确。

斐波那契数列的利用矩阵乘法、快速幂的算法版本的源代码如下:

//利用矩阵乘法、快速幂,计算斐波那契数列。
package fibonacci;
import java.math.BigInteger;
class FibonacciCalculator {
    static class FibonacciMatrixMultiple {
        public BigInteger a11;
        public BigInteger a12;
        public BigInteger a21;
        public BigInteger a22;

        public FibonacciMatrixMultiple(BigInteger p_a11, BigInteger p_a12,
                BigInteger p_a21, BigInteger p_a22) {
            this.a11 = p_a11;
            this.a12 = p_a12;
            this.a21 = p_a21;
            this.a22 = p_a22;
        }
    }

    public static FibonacciMatrixMultiple Multiply(
            FibonacciMatrixMultiple mat1, FibonacciMatrixMultiple mat2) {
        return new FibonacciMatrixMultiple(mat1.a11.multiply(mat2.a11).add(
                mat1.a12.multiply(mat2.a21)), mat1.a11.multiply(mat2.a12).add(
                mat1.a12.multiply(mat2.a22)), mat1.a21.multiply(mat2.a11).add(
                mat1.a22.multiply(mat2.a21)), mat1.a21.multiply(mat2.a12).add(
                mat1.a22.multiply(mat2.a22)));
    }

    static class FibonacciMatrix {
        public BigInteger a11;
        public BigInteger a21;

        public FibonacciMatrix(BigInteger p_a11, BigInteger p_a21) {
            this.a11 = p_a11;
            this.a21 = p_a21;
        }
    }

    public static FibonacciMatrix Multiply2(FibonacciMatrixMultiple mat1,
            FibonacciMatrix mat2) {
        return new FibonacciMatrix(mat1.a11.multiply(mat2.a11).add(
                mat1.a12.multiply(mat2.a21)), mat1.a21.multiply(mat2.a11).add(
                mat1.a22.multiply(mat2.a21)));
    }

    private static FibonacciMatrix getFibonacciMatrix(int n) {
        FibonacciMatrix resultMatrix = new FibonacciMatrix(
                BigInteger.valueOf(1), BigInteger.valueOf(1));
        FibonacciMatrixMultiple multiple = new FibonacciMatrixMultiple(
                BigInteger.valueOf(1), BigInteger.valueOf(1),
                BigInteger.valueOf(1), BigInteger.valueOf(0));
        while (n > 0) {
            if ((n & 1) == 1)
                resultMatrix = Multiply2(multiple, resultMatrix);
            n >>= 1;
            if (n > 0)
                multiple = Multiply(multiple, multiple);
        }
        return resultMatrix;
    }

    public static BigInteger getFibonacci(int index) {
        if (index < 1)
            return BigInteger.valueOf(0);
        if (index == 1)
            return BigInteger.valueOf(1);
        return getFibonacciMatrix(index - 2).a11;
    }
    
    public static void main(String[] args) {
		for (int i = 0; i < 20; i++) { //计算前20项
			System.out.println(getFibonacci(i));
		}
	}
}

利用矩阵乘法、快速幂的计算斐波那契数列效率是很高的。尤其当计算较大项(index大于65535)时,所花费的时间要比前面的方法花费的时间少至少一个数量级。

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

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

相关文章

场外个股期权是不是个股期权?场外个股期权和个股期权的区别

今天带你了解场外个股期权是不是个股期权&#xff1f;场外个股期权和个股期权的区别。场外个股期权是指在沪深交易所之外交易的个股期权&#xff0c;其本质是一种金融衍生品&#xff0c;允许投资者在股票交易场所外以特定价格买进或卖出证券。 个股期权作为一种重要的投资工具…

【机器学习】线性回归与逻辑回归的极致解析:从数学理论到实战案例

文章目录 1. 引言Python 代码示例 2. 线性回归2.1 线性回归的基本概念线性回归的定义数学表达式及模型假设 2.2 线性回归的工作原理最小二乘法&#xff08;Ordinary Least Squares, OLS&#xff09;梯度下降法在线性回归中的应用多元线性回归与一元线性回归的区别与联系 2.3 线…

面试经典算法150题系列-最长公共前缀

最长公共前缀 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 ""。 示例 1&#xff1a; 输入&#xff1a;strs ["flower","flow","flight"] 输出&#xff1a;"fl"示例 2&…

数据库学习(进阶)

数据库学习&#xff08;进阶&#xff09; Mysql结构:连接层&#xff1a;服务层&#xff08;核心层&#xff09;&#xff1a;存储引擎层&#xff1a;系统文件层&#xff1a; 存储引擎&#xff08;概述&#xff09;:存储引擎特点&#xff1a;InnoDB存储引擎&#xff1a;(为并发条…

c++顺序表初始(vector)

前言 std是一个容器和算法相关的库&#xff0c;顺序表作为一个常见的容器也在标准库中有相应的实现--vector。今天我们就来简单的认识一下vector的使用&#xff0c;并且简单的模拟实现一个我们的vector 具体vector类的描述可以参考vector - C Reference (cplusplus.com) 在不…

八股之 Java 常用框架

一、Spring 1.IOC 1.将一个类声明为 Bean 的注解有哪些? Component&#xff1a;通用的注解&#xff0c;可标注任意类为 Spring 组件。如果一个 Bean 不知道属于哪个层&#xff0c;可以使用Component 注解标注。Repository : 对应持久层即 Dao 层&#xff0c;主要用于数据库…

【网络 day1】

服务器可以循环接收客户端的数据&#xff1b;当客户端退出后&#xff0c; 服务器阻塞等待下一个客户端的连接&#xff0c;而后继续通信&#xff1b;当有客户端连接时&#xff0c; 服务器端 打印客户端的IP 和 Port信息&#xff1b;将代码的 send 和 recv 改为 write 和 read&am…

2024年5款值得推荐的图表数据可视化工具推荐,不会Excel做表必备!

只推荐5个数据可视化图表制作网站&#xff0c;保证让你相见恨晚&#xff01; 模板类型全、数量丰富&#xff0c;支持在线编辑&#xff0c;还免费~~ 1、Dycharts 推荐指数&#xff1a;☆☆☆☆☆ 网址&#xff1a;dycharts.com 这是一个功能强大且免费的在线数据可视化制作工…

产品分析 | 便利蜂

​产品信息 产品名称&#xff1a;便利蜂 Slogan&#xff1a;小小的幸福 在你身边 版本号&#xff1a;V1.11.3 大小&#xff1a;23.6M 体验环境&#xff1a;Android6.0.1 品牌概述 便利蜂成立于2016年12月&#xff0c;算是起步较早的企业了&#xff0c;17年2月就开了第一家…

记录一次edu web端渗透测试实录

0x01前言 由于是直接接到的相关需求&#xff0c;所以是针对性的一次渗透测试&#xff0c;以下内容仅仅作为思路分享以及打法扩展 0x02 进后台小妙招 弱口令永远是永恒不变的0day漏洞&#xff0c;这也是我们挖漏洞时的敲门砖&#xff0c;以下给出的是一个很神奇的关于寻找后台…

看 逆行人生

电影和我的职业本身有相关性&#xff0c;而且我特别喜欢徐峥执导的电影&#xff0c;这次的题材也算是碰上自己的胃口。 周六&#xff0c;下了大半天的雨&#xff0c;早上驱车到公司加班&#xff0c;下午六点多到时候特别想去看电影&#xff0c;果断再驱车从公司赶回来&#xff…

excel计算时间差-显示每堂课时间

TEXT(H2 - INDEX($H$2:$H$1000, MATCH(B2, $B$2:$B$1000, 0)), "mm:ss")import pandas as pd# 假设你已经加载了数据 df pd.read_excel(你的文件路径.xlsx)# 将开始时间列转换为datetime类型 df[开始时间] pd.to_datetime(df[开始时间])# 计算每个课堂号组内的时间…

批发供应系统:提升效率与竞争力的关键

在当今复杂多变的商业环境中&#xff0c;批发供应系统作为连接生产商、分销商与零售商的重要纽带&#xff0c;其效率与智能化水平直接决定了供应链的运作效率与市场竞争力。随着信息技术的飞速发展&#xff0c;尤其是大数据、云计算、人工智能&#xff08;AI&#xff09;及物联…

Python基础—数据分析中的可视化技巧

数据分析中的可视化技巧是帮助我们将复杂的数据转化为直观、易于理解的图表和图像的过程。这些技巧不仅有助于发现数据中的模式和趋势&#xff0c;还能增强数据故事的讲述能力。以下是一些常用的数据可视化技巧&#xff0c;以及相应的Python代码示例&#xff08;使用matplotlib…

Diffusion Model相关论文整理(二)

目录 1、AnoDDPM: Anomaly Detection With Denoising Diffusion Probabilistic Models Using Simplex Noise [CVPR Workshop 2022]2、Unsupervised Visual Defect Detection with Score-Based Generative Model[2022]3、DiffusionAD: Denoising Diffusion for Anomaly Detectio…

接口自动化-代码实现

接口自动化基础 1、接口自动化测试 接口自动化&#xff1a;使用工具或代码代替人对接口进行测试的技术测试目的&#xff1a; 防止开发修改代码时引入新的问题测试时机&#xff1a; 开发进行系统测试转测前&#xff0c;可以先进行接口自动化脚本的编写开发进行系统测试转测后&…

Tensorflow实现深度学习案例7:咖啡豆识别

本文为为&#x1f517;365天深度学习训练营内部文章 原作者&#xff1a;K同学啊 一、前期工作 1. 导入数据 from tensorflow import keras from tensorflow.keras import layers,models import numpy as np import matplotlib.pyplot as plt import os,PIL,p…

地平线旭日X3开发板--图像获取时间戳问题

需求 需要获得图像接收完成后的帧时间戳。 sensor f37, MIPI 通信 问题 按我的了解&#xff0c;一般是在内核中产生MIPI数据接收完成中断并打印时间戳&#xff0c; 一般是CLOCK_MONOTONIC方式的时间 &#xff0c; X3无法获得MIPI数据接收完成的时间戳。 X3平台HB_VIN_GetC…

4 - Linux远程访问及控制

目录 一、SSH远程管理 1. SSH概述 2.SSH的优点 3.配置OpenSSH客户端 4.sshd服务支持的两种验证方式 5. 使用SSH客户端程序 5.1 ssh - 远程登录 5.2 scp - 远程复制 6.配置密钥对验证 二、TCP Wrappers访问控制 1.TCP Wrappers 概述 2. TCP Wrappers 机制的基本原则 …

MS SQL Server partition by 函数实战二 编排考场人员

目录 需求 输出效果 范例运行环境 表及视图样本设计 功能实现 生成考场数据 生成重复的SQL语句 封装为统计视图 编写存储过程实现统计 小结 需求 假设有若干已分配准考证号的考生&#xff0c;准考证号示例&#xff08;01010001&#xff09;共计8位&#xff0c;前4位…