当前位置: 首页 > news >正文

【算法扩展】斐波那契查找算法 - JAVA

一、算法概述

斐波那契查找是一种在有序数组中进行查找的算法,它与二分查找类似,但使用斐波那契数列来确定分割点。算法的核心思想是将查找区间按照黄金分割比例(约0.618)进行划分,而不是像二分查找那样均分为二。这种分割方式在某些场景下可以获得更好的性能。

斐波那契数列基础知识

斐波那契数列定义为:F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2) (n≥2)

前几项为:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144...

二、时间复杂度

斐波那契查找的时间复杂度为 O(log n),与二分查找相同。空间复杂度为 O(1),只需存储几个变量。

三、查找思路与公式

1. 基本思路

  1. 找到不小于数组长度n的最小斐波那契数F(k)
  2. 将数组长度扩展到F(k)-1(必要时填充)
  3. 使用F(k-1)-1作为分割点,将数组分为两部分:
    • 前半部分长度为F(k-1)-1
    • 后半部分长度为F(k-2)

2. 分割公式

在斐波那契查找中,分割点的计算公式为:

mid = low + F(k-1) - 1
  • F(k-1) 是斐波那契数列中的一项,k是使得F(k)-1不小于数组长度的最小值。
  • 在斐波那契查找中,F(k-1)对应黄金分割点左边的长度
  • 这个公式反映了黄金分割比例(约为1:0.618)。当数组按照这个比例分割时,大约61.8%的数据会在左边,38.2%的数据会在右边,这就是利用斐波那契数列进行查找的数学基础。

3. 调整斐波那契序列

  • 当目标在右半部分时:k = k-2,因为右半部分长度约为F(k-2)
  • 当目标在左半部分时:k = k-1,因为左半部分长度约为F(k-1)-1

四、代码示例

public class FibonacciSearch {public static int fibonacciSearch(int[] arr, int key) {int n = arr.length;if (n == 0) return -1;// 构造斐波那契数列int fibMMinus2 = 0;   // F(k-2)int fibMMinus1 = 1;   // F(k-1)int fibM = fibMMinus1 + fibMMinus2;  // F(k)// 找到不小于n的最小斐波那契数while (fibM < n) {fibMMinus2 = fibMMinus1;fibMMinus1 = fibM;fibM = fibMMinus1 + fibMMinus2;}// 定义数组的偏移量int offset = -1;// 循环查找while (fibM > 1) {// 计算比较点的索引int i = Math.min(offset + fibMMinus2, n - 1);// 比较并决定向左还是向右if (arr[i] < key) {// 目标在右半部分,调整斐波那契数列fibM = fibMMinus1;fibMMinus1 = fibMMinus2;fibMMinus2 = fibM - fibMMinus1;offset = i;  // 更新偏移量} else if (arr[i] > key) {// 目标在左半部分,调整斐波那契数列fibM = fibMMinus2;fibMMinus1 = fibMMinus1 - fibMMinus2;fibMMinus2 = fibM - fibMMinus1;} else {// 找到目标return i;}}// 检查最后一个元素if (fibMMinus1 == 1 && offset + 1 < n && arr[offset + 1] == key) {return offset + 1;}// 未找到目标return -1;}public static void main(String[] args) {int[] arr = {5, 10, 15, 20, 25, 30, 35, 40, 45, 50};int key = 25;int result = fibonacciSearch(arr, key);if (result != -1) {System.out.println("元素 " + key + " 在数组中的索引位置: " + result);} else {System.out.println("元素 " + key + " 不在数组中");}}
}

五、示例

假设有一个有序数组 [5, 10, 15, 20, 25, 30, 35, 40, 45, 50],查找元素25:

  1. 数组长度为10,找到不小于10的斐波那契数F(7)=13
  2. F(6)=8, F(5)=5
  3. 第一次比较:mid = 0 + F(6) - 1 = 0 + 8 - 1 = 7,arr[7] = 40 > 25
    • 目标在左半部分,调整斐波那契数:F(7)→F(5), F(6)→F(5), F(5)→F(4)
  4. 第二次比较:mid = 0 + F(4) - 1 = 0 + 3 - 1 = 2,arr[2] = 15 < 25
    • 目标在右半部分,调整斐波那契数:F(5)→F(4), F(5)→F(3), F(4)→F(2)
    • 更新offset = 2
  5. 第三次比较:mid = 2 + F(2) - 1 = 2 + 1 - 1 = 2,arr[2] = 15 < 25
    • 目标在右半部分,调整斐波那契数:F(4)→F(3), F(3)→F(2), F(2)→F(1)
    • 更新offset = 2
  6. 第四次比较:mid = 2 + F(1) - 1 = 2 + 1 - 1 = 2,arr[2] = 15 < 25
    • 目标在右半部分,调整斐波那契数:F(3)→F(2), F(2)→F(1), F(1)→F(0)
    • 更新offset = 2
  7. 检查offset+1 = 3,arr[3] = 20 < 25
  8. 检查offset+2 = 4,arr[4] = 25 = 25,找到目标!

六、适用场景和优缺点

适用场景

  • 磁盘等外存查找:减少对前半部分的访问
  • 大型有序数组:在某些数据分布下比二分查找更高效
  • 减少比较次数的场景:按黄金分割比搜索有时能减少平均比较次数

优点

  • 分割更自然:按照黄金分割比例划分区间
  • 在某些场景下效率更高:特别是当数据访问成本不均匀时
  • 只需加减运算:不需要像二分查找那样进行除法操作

缺点

  • 实现较复杂:需要管理斐波那契数列和相关逻辑
  • 需要额外处理:当数组长度不是斐波那契数减1时需要特殊处理
  • 优势不总是明显:在现代计算机中,优势可能不如理论预期

七、总结

斐波那契查找是一种利用黄金分割原理的查找算法,它按照斐波那契数列的特定比例划分查找区间。虽然与二分查找时间复杂度相同,但在某些特定场景下可能更有效率。这种算法展示了如何利用数学性质优化搜索过程,是算法设计思想的一个很好例证。

相关文章:

  • Python结合QT进行开发
  • ES6函数、对象和面向对象扩展
  • QT6 源(66)篇三:阅读与注释类 QAbstractSpinBox ,这是螺旋框的基类,附上源码
  • QML Image 组件详解
  • Stm32 烧录 Micropython
  • 深度学习框架搭建(Vscode/Anaconda/CUDA/Pytroch)
  • 小牛电动:荣登央视舞台,引领智能出行新潮流
  • 26考研——输入/输出系统(7)
  • 基于Redis实现-用户签到
  • 数据库 AI 助手测评:Chat2DB、SQLFlow 等工具如何提升开发效率?
  • 前端HTML基础知识
  • 超稳定性理论
  • AI Agent(2):Agent技术架构
  • 2025五一杯B题超详细解题思路
  • 【深度学习新浪潮】小米MiMo-7B报告内容浅析
  • 如何进行 JVM 性能调优?
  • Linux-04-搜索查找类命令
  • mono map
  • 【验证技能】文档要求和好文档注意点
  • 无缝监控:利用 AWS X-Ray 增强 S3 跨账户复制的可见性
  • 五大白酒去年净利超1500亿元:贵州茅台862亿领跑,洋河营收净利齐降
  • 申活观察|咖香涌动北外滩,带来哪些消费新想象?
  • 解放日报:硬科企业由此迈出“市场第一步”
  • 首开股份:一季度净利润亏损约10.79亿元,签约金额63.9亿元
  • 中国强镇密码丨洪泽湖畔的蒋坝,如何打破古镇刻板印象
  • 比黄油年糕热量还高,这个火爆全网的甜品劝你慎吃