文章目录

  • 一、斐波那契查找算法概述
    • 1.1 什么是斐波那契查找算法
    • 1.2 什么是斐波那契数列
    • 1.3 斐波那契查找算法的思想
  • 二、斐波那契查找的基本步骤
  • 三、斐波那契查找的代码实现

一、斐波那契查找算法概述

1.1 什么是斐波那契查找算法

斐波那契搜索(Fibonacci search) ,又称斐波那契查找,是区间中单峰函数的搜索技术。斐波那契查找就是在二分查找的基础上根据斐波那契数列进行分割的。

斐波那契查找同样是查找算法家族中的一员,它要求数据是有序的(升序或降序)。斐波那契查找采用和二分查找/插值查找相似的区间分割策略,都是通过不断的分割区间缩小搜索的范围

1.2 什么是斐波那契数列

要想具体学习斐波那契查找算法,就不得不先了解一下斐波那契数列。

斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为 “兔子数列”。

如下图所示,就是一个斐波那契数列:

在数学上,斐波那契数列被以如下递推的方法定义:
F(0)=0,F(1)=1F(0) = 0, \ F(1) = 1 F(0)=0, F(1)=1

F(n)=F(n−1)+F(n−2)(n≥2,n∈N∗)F(n) = F(n-1) + F(n-2) \qquad (n≥2,n∈N^*) F(n)=F(n−1)+F(n−2)(n≥2,n∈N∗)

从斐波那契的递推公式我们可以总结出重要一点:斐波那契数列从第三项开始,每一项都等于前两项之和

1.3 斐波那契查找算法的思想

由 1.2 我们可以得知斐波那契数列的特点,而我们可以利用它的特点来做区间分割:可以将一个长度为 F(n) 的数组看作左右两段,左边一段长度是 F(n-1),右边一段长度是 F(n-2)。

正是上面这样的区间分割想法,使斐波那契数列和数组联系到了一起。这种分割思想亦是斐波那契查找算法的基础。

斐波那契查找算法相对于二分查找和插值查找的基本思路是一致的,其中最重要的区别就是它们的查找点(或称中间值)的确定。斐波那契查找算法的查找点的计算公式如下
mid=left+F(n−1)−1mid = left+F(n-1)-1 mid=left+F(n−1)−1
【基本思想】

完整的斐波那契查找的基本思想如下:在斐波那契数列找一个等于或第一个大于查找表中元素个数的数 F[n],然后将原查找表的长度扩展为 Fn (如果要补充元素,则重复补充原查找表最后一个元素,直到原查找表中满足 F[n] 个元素);扩展完成后进行斐波那契分割,即 F[n] 个元素分割为前半部分 F[n-1] 个元素,后半部分 F[n-2] 个元素;接着找出要查找的元素在哪一部分并递归,直到找到。

二、斐波那契查找的基本步骤

从上面我们知道了斐波那契查找算法的基本思想,根据它的基本思想,斐波那契查找的基本步骤可以分为以下几步:

  1. 构建斐波那契数列;
  2. 找出查找表长度对应的斐波那契数列中的元素 F(n);
  3. 如果查找表长度小于斐波那契数列中对应的元素 F(n) 的值,则补充查找表(以查找表最后一个元素补充);
  4. 根据斐波那契数列特点对查找表进行区间分隔,确定查找点 mid = left+F(n-1)-1(减 1 是因为数组下标从 0 开始);
  5. 判断中间值 arr[mid] 和目标值的关系,确定下一步策略:
    • 如果目标值小于中间值,说明目标值在左区间。由于左区间长度为 F(n-1),因此 n 应该更新为 n-1,然后再次执行 4、5 两步;
    • 如果目标值大于中间值,说明目标值在右区间。由于右区间长度为 F(n-2),因此 n 应该更新为 n-2,然后再次执行 4、5 两步;
    • 如果目标值等于中间值,说明找到了目标值。但此时还需判别该目标值是原查找表中的元素还是填充元素:
      • 如果是原查找表中的元素,直接返回索引;
      • 如果是填充元素,则返回原查找表的最后一个元素的索引,即 arr.length-1。(因为扩展数组是以原查找表最后一个元素来填充,如果目标值是填充元素,则说明原查找表最后一个元素值就是目标值)

三、斐波那契查找的代码实现

根据斐波那契查找算法的基本步骤,实现出的代码如下:

/*** 斐波那契查找算法* @param arr   查找表* @param findValue 目标值* @return int  目标值在查找表中的索引*/
public static int fibonacciSearch(int[] arr, int findValue){int i = 0;int mid;    // 中间值int left = 0;   // 区间左端int right = arr.length-1;   // 区间右端// 1. 创建斐波那契数列int[] fibonacci = getFibonacci(20);// 2. 获取斐波那契数列中等于或者第一个大于数组长度的数while(fibonacci[i] < arr.length){i++;}// 3. 按照斐波那契数列中的元素长度拷贝一个查找表int[] temp = Arrays.copyOf(arr, fibonacci[i]);// 4. 以原查找表最后一个元素补齐临时查找表长度for (int j=arr.length; j<temp.length; j++){temp[j] = arr[arr.length-1];}// 5. 循环判断while (left <= right){mid = left + fibonacci[i-1]-1;  // 计算查找点if (temp[mid] < findValue){  // 如果查找点小于目标值,说明在右区间left = mid + 1; // 右区间起点i -= 2; // 右区间长度是 f[i-2],所以要把 i 换成 i-2}else if (temp[mid] > findValue){    // 如果查找点大于目标值,说明在左区间right = mid - 1; // 左区间终点i -= 1; // 左区间长度是 f[i-1],根据所以要把 i 换成 i-1}else{  // 如果相等,说明找到了/* 找到存在两种可能:一是找到的是原查找表中的元素,二是找到的是填充值。因此需要判别*/if (mid <= right){  // 如果是原查找表中的元素,直接返回索引return mid;}else{  // 如果找到的是填充值,则返回原查找表最后一个索引return right;}}}return -1;
}/*** 创建斐波那契数列* @param maxSize   斐波那契数列长度* @return int[]    斐波那契数列*/
public static int[] getFibonacci(int maxSize){int[] fibonacci = new int[maxSize];fibonacci[0] = 0;fibonacci[1] = 1;for (int i=2; i<maxSize; i++){fibonacci[i] = fibonacci[i-1] + fibonacci[i-2];}return fibonacci;
}

斐波那契(黄金分割法)查找算法相关推荐

  1. 我所知道查找算法之斐波拉契(黄金分割法)查找

    作者前言 大家好,我是阿濠,今篇内容跟大家分享的是查找算法之斐波那契(黄金分割法)查找,很高兴分享到segmentfault与大家一起学习交流,初次见面请大家多多关照,一起学习进步. 一.斐波那契数列 ...

  2. 数据结构与算法-查找算法(二分查找,插值查找,斐波那契(黄金分割法)查找)

    查找算法 以下三种算法的基本思想相同,都是利用递归来寻找 二分查找 思路分析 1.首先确定该数组的中间下标,min = (left + right) / 2 2.然后让需要查找的的数findVal和a ...

  3. JavaScript实现闭式函数计算特定位置的斐波那契数fibonacciNthClosedForm算法(附完整源码)

    JavaScript实现闭式函数计算特定位置的斐波那契数fibonacciNthClosedForm算法(附完整源码) fibonacciNthClosedForm.js完整源代码 fibonacci ...

  4. JavaScript实现动态规划方法计算特定位置的斐波那契数fibonacciNth算法(附完整源码)

    JavaScript实现动态规划方法计算特定位置的斐波那契数fibonacciNth算法(附完整源码) fibonacciNth.js完整源代码 fibonacciNth.js完整源代码 export ...

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

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

  6. C语言DP备忘计算指数N的斐波那契级数的算法(附完整源码)

    C语言DP备忘计算指数N的斐波那契级数的算法 C语言DP备忘计算指数N的斐波那契级数的算法完整源码(定义,实现,main函数测试) C语言DP备忘计算指数N的斐波那契级数的算法完整源码(定义,实现,m ...

  7. 斐波那契数列系列算法最优复杂度-------O(logN)

    斐波那契数列系列算法最优复杂度--时间复杂度优化到O(LogN) 对于菲薄那契系列问题的探讨很多,下面就以两个例子来分析: 案例 一: 在迷迷糊糊的大草原上,小红捡到了n根木棍,第i根木棍的长度为i, ...

  8. 数据结构三大查找算法(二分查找、插值查找、斐波那契数列查找)C语言实现

    文章目录 查找 二分查找(折半查找) 插值查找 斐波拉契查找 总结: 查找 查找是在大量的信息里面寻找一个特定的信息元素 (1)静态查找和动态查找: 静态或者动态都是针对查找表而言的.动态表指查找表中 ...

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

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

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

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

最新文章

  1. MAP/CAP信令常见消息
  2. 清华学生计划表上热搜,大写的服!
  3. Mac OS 错误代码 -8072的可行解决方法
  4. 006python路--深浅拷贝
  5. 不自由な放課後 + 正しいメイドの躾かた 汉化补丁
  6. Java语言程序设计 上机实验2 掌握Java的基本语言成分和流程控制语句。 掌握Java中数组的使用,理解引用数据类型。 掌握String类的使用。...
  7. 面向对象的三个基本特征(讲解)-转载
  8. 吴恩达|机器学习作业3.1前馈神经网络
  9. OVM-V1.2正式发布,新增实时监控功能,支持一键升级
  10. hashmap7源码浅析及与hashmap8的比较
  11. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第1节 常用函数接口_10_常用的函数式接口_Consumer接口中的默认方法andThen...
  12. 【易错点 学习笔记】Solidity语法constant/view/pure
  13. (二)使用selenium爬取拉钩招聘网信息并存入csv文件
  14. java 安全包_信息加密系统设计(依托Java平台安全包)
  15. 一键脚本搭建docker redis 集群(cluster)
  16. 单线激光雷达的外参标定方法
  17. 安装JDK及配置环境变量
  18. 什么是产品运营?文中这个举例感觉让我思路明朗了许多
  19. USB接口类型与线序
  20. 深入研究simulink建模与仿真之输入端口模块(Inport)的几种不同的图标

热门文章

  1. 辗转相除法求最大公因数
  2. 4r照片尺寸是多大_4r照片尺寸(正常照片是5寸还是6寸)
  3. Windows启动过程详解
  4. SourceTree这是一个无效源路径(更改git账号和密码导致无效源路径看这里)
  5. python中最大值函数,python中如何获取最大值函数
  6. python-docx 复制一页_python 怎么用docx读取word的某一页然后放到新的word文档中?...
  7. Python 数据处理库 pandas
  8. 夫妻宫十星所暗示的未来另一半
  9. mysql select 临时表_mysql临时表的产生
  10. 在VMware虚拟机上安装 Win7 操作系统