首页 > 其他分享 >浅析斐波那契数列在代码中的应用

浅析斐波那契数列在代码中的应用

时间:2023-10-13 14:23:19浏览次数:42  
标签:数列 浅析 斐波 数组 那契 散列 节点

by emanjusaka from ​ https://www.emanjusaka.top/archives/9 彼岸花开可奈何
本文欢迎分享与聚合,全文转载请留下原文地址。

前言

斐波那契数列在代码中的应用是比较常见的,下面让我们来了解下一个数学上的数列在代码中会有哪些应用。了解斐波那契,可以给我们提供解决某些问题的思路,优化解决问题的方法。

一、定义

F0 = 0,F1 = 1,Fn = F(n - 1) + F(n - 2)

F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
  • 从 F2 开始任意一位都是前两位之和。
  • 从 F2 开始任意一位与前一位相比的比值,都无限趋近于 (√5 - 1)/2 = 0.618 因此基于黄金分割的计算应用,也被称为斐波那契应用。

二、三种计算方法

2.1、循环计算

public double fibonacci(int n) {
    int f1 = 1;
    int f0 = 0;
    if (n < 2) return n;
    int num = n - 1;
    while (num > 0) {
        f1 += f0;
        f0 = f1 - f0;
        num --;
    }
    return f1;
}

2.2、递归计算

public int fibonacciRecursion(int n) {
    if (n < 2){
        return n;
    } else {
        return (fibonacciRecursion(n - 1) + fibonacciRecursion(n - 2));
    }
}

2.3、比奈公式

public double fibonacciClosedForm(long position) {
    int maxPosition = 75;
    if (position < 1 || position > maxPosition) {
        throw new RuntimeException("Can't handle position smaller than 1 or greater than 75");
    }
    double sqrt = Math.sqrt(5);
    double phi = (1 + sqrt) / 2;
    return Math.floor((Math.pow(phi, position)) / sqrt + 0.5);
}

三、散列函数

3.1、除法散列

在用来设计散列函数的除法散列法中,通过取 K 除以 M 的余数,将关键字 K 映射到 M 个槽中的某一个位置上,即散列函数为:h(K) = K mod M 表格大小通常是 2 的幂。

另外除法散列的一个显着缺点是除法在大多数现代架构(包括 x86)上都是微编程的,并且可能比乘法慢 10 倍。

3.2、乘法散列

乘法散列法整体包含两步:

  • 用关键字k乘上常数A(0<A<1),并去除kA的小数部分
  • 用m乘以这个值,再取结果的底floor 公式:h(K)=Math.floor[m(aK mod 1)]

步骤

  • 假设某计算机的字长为 ww 位,而 kk 正好可容于一个字中(k<2wk<2w)
  • 现在选取范围[0,2w]内的任意数值 ss,k×sk×s 即可用R1·2w+R0R1·2w+R0来表示
  • 因此(k·A)mod1=k·s/2w(k·A)mod1=k·s/2w就是将k×sk×s整体向右平移 ww 位,此时R0R0即为小数部分
  • 再乘以 2m2m 相当于左移 mm 位,散列值h(k)h(k) 为 R0R0 的前 m 位。

乘法散列只需要单个整数乘法和右移,使其成为计算速度最快的哈希函数之一。但乘法散列可能会在变更计算因子后,较高值的输入位不会影响较低值的输出位,问题体现在元素分散不均,不满足严格的雪崩标准。所以通常在会进行异或操作

乘法散列容易受到导致扩散不良的“常见错误”的影响——较高值的输入位不会影响较低值的输出位。在乘法步骤对此进行校正之前,输入上的变换将保留的最高位的跨度向下移动,并将它们异或或加到键上。所以在输入上的变换将保留的最高位的跨度向下移动,并将它们异或操作或者加到键上。例如 HashMap 的扰动函数。

3.3、斐波那契散列

其实斐波那契散列是一种特殊形式的乘法散列,只不过它的乘法因子选择的是一个黄金分割比例值,所以叫做斐波那契散列。

斐波那契散列的特性在于将“大数映射到小数”的计算结果在表空间上是均匀分布的,且计算满足乘法散列效率高。

四、简单应用

4.1、伪随机数生成

斐波那契数列可以用于生成伪随机数序列。虽然斐波那契数列本身不是真正的随机数序列,但通过适当的变换和截取,可以得到具有一定随机性的序列。

package top.emanjusaka;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        System.out.println(fibonacciRandom(5, 8));
    }

    public static List<Integer> fibonacciRandom(int seed, int length) {
        List<Integer> fibSequence = new ArrayList<>(Arrays.asList(0, 1));
        while (fibSequence.size() < seed + length) {
            int nextNumber = fibSequence.get(fibSequence.size() - 1) + fibSequence.get(fibSequence.size() - 2);
            fibSequence.add(nextNumber);
        }
        List<Integer> randomSequence = new ArrayList<>();
        for (int i = seed; i < seed + length; i++) {
            randomSequence.add(fibSequence.get(i));
        }
        return randomSequence;
    }
}

4.2、AVL 二叉树

在AVL树中,斐波那契数列可以用于平衡因子的调整和旋转操作。

AVL树是一种自平衡二叉搜索树,它要求左右子树的高度差不超过1,以保持树的平衡性。当对AVL树进行插入或删除操作时,可能会破坏树的平衡,这时需要对树进行旋转操作来恢复平衡。

在AVL树的旋转操作中,涉及到更新节点的高度信息。通常,节点的高度可以通过其子节点的高度来计算。而斐波那契数列正好提供了方便的计算方式。

具体应用如下:

  1. 插入操作:当在AVL树中插入一个节点时,会导致从插入节点到根节点路径上的某些节点的平衡因子发生变化。通过向上回溯,我们可以更新路径上的节点的高度,并检查它们的平衡状态。如果某个节点的平衡因子超过了允许的范围,就需要进行旋转操作来恢复平衡。在这个过程中,斐波那契数列可以用于更新节点的高度信息。
  2. 删除操作:当从AVL树中删除一个节点时,也会导致树的平衡性被破坏。类似插入操作,我们需要从删除节点的父节点向上回溯并更新节点的高度信息。如果某个节点的平衡因子超过了允许的范围,就需要进行旋转操作来恢复平衡。斐波那契数列可以用于更新高度信息。
  3. 旋转操作:斐波那契数列在AVL树的旋转操作中扮演了重要的角色。旋转操作包括左旋和右旋,它们通过改变树的结构来保持平衡。在旋转操作中,涉及到节点的高度信息的更新,而斐波那契数列可以方便地计算节点的高度。

4.3、最大公约数

斐波那契数列在最大公约数计算中有一个有趣的应用,称为"连续整除性质"。

假设我们有两个正整数a和b,并且a > b。如果a可以被b整除,那么a与斐波那契数列中位于第a个位置(从1开始计数)的数具有相同的最大公约数。换句话说,gcd(a, b) = gcd(b, F(a)),其中F(n)表示斐波那契数列中第n个数。

这个性质的证明基于斐波那契数列的递推关系和欧几里得算法的原理。简单来说,当a能够被b整除时,可以将a表达为b的倍数加上剩余部分,即a = qb + r,其中q是商,r是余数。然后我们可以使用斐波那契数列的递推关系,即F(n) = F(n-1) + F(n-2),将a和b替换为它们的等价表达式:

gcd(a, b) = gcd(qb + r, b) = gcd(b, r)

这就意味着最初的问题可以转化为更小的问题,即求b和r的最大公约数。通过重复应用这个性质,我们最终可以将问题简化为求最小的b和斐波那契数列中的一个数之间的最大公约数。

这个连续整除性质可以用于计算任意两个正整数的最大公约数,而不需要直接使用辗转相除法。通过与斐波那契数列相关联,它提供了一种更高效的方法来计算最大公约数。

需要注意的是,连续整除性质只适用于a > b的情况,因此在应用时需要确保a和b的大小顺序。

4.4、合并排序算法

在合并排序算法中,斐波那契数列可以用于确定合并的子数组大小。

合并排序是一种基于分治思想的排序算法,它将待排序的数组不断地拆分为较小的子数组,并对这些子数组进行排序,然后再将排好序的子数组合并为一个有序数组。斐波那契数列在确定子数组大小时可以发挥作用。

具体应用如下:

  1. 确定初始子数组大小:在合并排序的初始阶段,需要确定用于拆分数组的子数组大小。常规的合并排序算法中,通常选择固定的子数组大小(例如2)。而使用斐波那契数列则可以提供更灵活的选项。通过斐波那契数列,可以依次选择递增的子数组大小,使得拆分后的子数组大小趋近于黄金比例(1:1.618),以达到更好的平衡。
  2. 动态调整子数组大小:在合并排序的过程中,当两个子数组合并时,需要确定合并后的子数组大小。传统的合并排序中,通常是将两个子数组完全合并为一个新的子数组。而使用斐波那契数列,则可以根据斐波那契数列的顺序,选择部分元素进行合并,以减少合并操作的次数。这样可以降低算法的复杂度。

斐波那契数列在合并排序算法中的应用,主要是为了确定子数组的大小,以实现更灵活和高效的排序过程。利用斐波那契数列的特性,可以使合并排序算法更加平衡、快速和优化。

本文原创,才疏学浅,如有纰漏,欢迎指正。如果本文对您有所帮助,欢迎点赞,并期待您的反馈交流,共同成长。

原文地址: https://www.emanjusaka.top/archives/9

微信公众号:emanjusaka的编程栈

标签:数列,浅析,斐波,数组,那契,散列,节点
From: https://www.cnblogs.com/emanjusaka/p/page_9.html

相关文章

  • 斐波那契数列二项式
    在阅读CSDN时看到的。对于\(Fibonacci\)数列。存在\(Fibonacci_{2n}=Fibonacci_n\times(Fibonacci_{n-1}+Fibonacci_{n+1})\)。证明:我们知道\(Fibonacci\)有一个这个东西。\(\begin{bmatrix}f_{2n+1}&f_{2n}\\f_{2n}&f_{2n-1}\end{bmatrix}=\begin{......
  • 浅析森林烟火AI检测算法的应用及场景使用说明
    一、方案背景现有的森林防火监测系统落后,以人工地面巡护、瞭望塔高点巡查为主,存在巡护范围有限、巡护效率低等问题,建立健全的森林防火风险预警体系,实现对森林、林场等场景的全天候智能自动监测、火情预警,及时发现森林火灾并辅助决策,是当前林业管理的重要任务。二、方案概述旭帆......
  • awr_plan_change脚本中平均执行时间不正确浅析?
    awr_plan_change.sql脚本是KerryOsborne的一个脚本,这个脚本也是我非常喜欢并且经常使用的一个脚本。脚本如下所示set lines 155col execs for 999,999,999col avg_etime for 999,999.999col avg_lio for 999,999,999.9col sql_id for a16col begin_interval_tim......
  • 斐波那列数列的讲解过程
    python案例解释的有点不好,多多包含deff1(n):ifn<=2:return1;else:returnf1(n-1)+f1(n-2)#print(f1(6))"""示例1解释一下他是如何等8的,递归不是直接返回值再去传递给自身函数,比如n=4的时候,那么f1(4-1)+f1(4-2)=f1(3)+f1(2)不是......
  • 算法:打印斐波那契数列的前30项(JS)
    打印斐波那契数列的前30项提示:斐波那契数列的前两项是1,其他项是之前两项之和1functionfibonacciIterative(n){2if(n<=0){//如果输入的n小于等于0,表示输入错误,返回错误提示3return"输入错误,请输入正整数";4}5leta=1;//初始化......
  • 浅析C++ atomic
    早在C++11就在STL中引入了原子操作支持了。大部分时候,我使用C++11的atomic仅仅是为了原子地操作特定的一个变量,比如load、store、fetch_add等等。然而实际上,C++11的原子操作带着的memoryorder还能起到memorybarrier的作用。本文会从头介绍C++11原子变量的用法,使用的注意事项以及......
  • intel-RDT技术浅析
    前言本文适合于想要了解RDT技术的人阅读,会涉及到RDT技术的硬件机制,需要对CPU的socket、core、thread等概念有一定的了解。RDT技术简介RDT技术全称ResourceDirectorTechnology,RDT技术提供了LLC(Lastlevelcache)以及MB(MemoryBandwidth)内存带宽的分配和监控能力。RDT的主要功......
  • pig4cloud框架系列二:表结构浅析
    继系列一后,此篇简单讲一下表结构及每个表的作用1,sys_user:用户表,存储用户信息。2,sys_role:角色表3,sys_user_role:用户角色的定义,一个用户可以有多个角色,1对多的关系。4,sys_menu:菜单表,项目所有的菜单都维护在该表中。5,sys_role_menu:角色菜单表,定义每种角色具有哪些菜单,用户权限的......
  • 关于斐波那契数列 - 2 (平方的和)
    令斐波那契数列的第\(i\)项定义为\(b_i\)。再令\(f_n=\underset{i=1}{\overset{n}{\sum}}b^2_i\)结论:\(f_n=b_n\timesb_{n+1}\)首先,不难发现,该结论对于\(n=1\)和\(n=2\)一定是成立的\[f_1=1=1\times1\]\[f_2=1+1=2=1\times2\]......
  • 关于斐波那契数列 - 1
    令斐波那契数列第\(i\)个为\(F_i\)\(F_0=0,F_1=1,F_2=1\…\…\)结论:\(F_n^2=F_{n-1}F_{n+1}-(-1)^n\)不难发现,这一结论对于\(n=1\)显然是成立的接下来,运用数学归纳法若该结论对于\(n=k-1\)成立则\(F_{k-1}^2=F_{k-2}F_{k}-(-1)^{k......