Javascript 斐波那契搜索-迭代与递归(Fibonacci Search)

news2024/10/5 16:21:03

        给定一个大小为 n 的排序数组 arr[] 和要在其中搜索的元素 x。如果 x 存在于数组中,则返回 x 的索引,否则返回 -1。 
例子: 
输入:  arr[] = {2, 3, 4, 10, 40}, x = 10
输出:  3
元素 x 出现在索引 3 处。

输入:  arr[] = {2, 3, 4, 10, 40}, x = 11
输出:  -1
元素 x 不存在。

        斐波那契搜索是一种基于比较的技术,它使用斐波那契数来搜索排序数组中的元素。
与二分查找的相似之处:
        1、适用于排序数组
        2、分而治之的算法。
        3、具有 Log n 时间复杂度。
与二分查找的区别:
        1、斐波那契搜索将给定数组分成不相等的部分
        2、二分查找使用除法运算符来划分范围。斐波那契搜索不使用 /,而是使用 + 和 -。在某些 CPU 上,除法运算符的成本可能很高。
        3、斐波那契搜索在后续步骤中检查相对较近的元素。因此,当输入数组很大,无法容纳 CPU 缓存甚至 RAM 时,斐波那契搜索可能会很有用。
背景: 
        斐波那契数被递归地定义为 F(n) = F(n-1) + F(n-2)、F(0) = 0、F(1) = 1。前几个斐波那契数是 0、1、 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …
观察: 
下面的观察用于范围消除,因此用于 O(log(n)) 复杂度。  
F(n - 2) ≈ (1/3)*F(n) 且
F(n - 1) ≈ (2/3)*F(n)。
算法: 
设要查找的元素为x。
        这个想法是首先找到大于或等于给定数组长度的最小斐波那契数。令找到的斐波那契数为 fib(第 m 个斐波那契数)。我们使用第 (m-2) 个斐波那契数作为索引(如果它是有效索引)。设第(m-2)个斐波那契数为i,我们将arr[i]与x进行比较,如果x相同,则返回i。否则,如果 x 更大,则对 i 之后的子数组进行递归,否则对 i 之前的子数组进行递归。
下面是完整的算法 
设 arr[0..n-1] 为输入数组,要搜索的元素为 x。
        1、找到大于或等于 n 的最小斐波那契数。令这个数字为 fibM [第 m 个斐波那契数]。令其前面的两个斐波那契数为 fibMm1 [(m-1) 个斐波那契数] 和 fibMm2 [(m-2) 个斐波那契数]。
        2、当数组有要检查的元素时: 
                2.1、将 x 与 fibMm2 覆盖范围的最后一个元素进行比较
                2.2、如果x 匹配,则返回索引
                2.3、否则,如果x 小于该元素,则将三个斐波那契变量向下移动两个斐波那契,表示消除剩余数组的大约后三分之二。
                2.4、否则x 大于该元素,将三个斐波那契变量向下移动一位斐波那契。重置索引的偏移量。这些一起表明剩余阵列的大约前三分之一被消除。
        3、由于可能还剩下一个元素可供比较,因此检查 fibMm1 是否为 1。如果是,则将 x 与该剩余元素进行比较。如果匹配,则返回索引。

// Javascript program for Fibonacci Search 
   
/* Returns index of x if present, else returns -1 */
function fibMonaccianSearch(arr, x, n) 

    /* Initialize fibonacci numbers */
    let fibMMm2 = 0; // (m-2)'th Fibonacci No. 
    let fibMMm1 = 1; // (m-1)'th Fibonacci No. 
    let fibM = fibMMm2 + fibMMm1; // m'th Fibonacci 
   
    /* fibM is going to store the smallest Fibonacci 
    Number greater than or equal to n */
    while (fibM < n) 
    { 
        fibMMm2 = fibMMm1; 
        fibMMm1 = fibM; 
        fibM = fibMMm2 + fibMMm1; 
    } 
   
    // Marks the eliminated range from front 
    let offset = -1; 
   
    /* while there are elements to be inspected. Note that 
    we compare arr[fibMm2] with x. When fibM becomes 1, 
    fibMm2 becomes 0 */
    
    while (fibM > 1) 
    { 
        // Check if fibMm2 is a valid location 
        let i = Math.min(offset + fibMMm2, n-1); 
   
        /* If x is greater than the value at index fibMm2, 
        cut the subarray array from offset to i */
        if (arr[i] < x) 
        { 
            fibM = fibMMm1; 
            fibMMm1 = fibMMm2; 
            fibMMm2 = fibM - fibMMm1; 
            offset = i; 
        } 
   
        /* If x is less than the value at index fibMm2, 
        cut the subarray after i+1 */
        else if (arr[i] > x) 
        { 
            fibM = fibMMm2; 
            fibMMm1 = fibMMm1 - fibMMm2; 
            fibMMm2 = fibM - fibMMm1; 
        } 
   
        /* element found. return index */
        else return i; 
    } 
   
    /* comparing the last element with x */
    if(fibMMm1 && arr[n-1] == x){ 
      return n-1 
    } 
   
    /*element not found. return -1 */
    return -1; 

   
/* driver code */
    let arr = [10, 22, 35, 40, 45, 50, 80, 82,85, 90, 100,235]; 
    let n = arr.length; 
    let x = 235; 
    let ind = fibMonaccianSearch(arr, x, n); 
    if(ind>=0){ 
       document.write("Found at index: " + ind); 
    }else{ 
       document.write(x + " isn't present in the array"); 
    } 
   
// This code is contributed by _saurabh_jaiswal 

输出
发现于索引:11
插图: 
让我们通过下面的例子来理解算法:  

示例假设:基于 1 的索引。目标元素 x 为 85。数组长度 n = 11。
        大于或等于 11 的最小斐波那契数为 13。根据我们的插图,fibMm2 = 5、fibMm1 = 8 和 fibM = 13。
        另一个实现细节是偏移变量(零初始化)。它标志着已被淘汰的范围,从前面开始。我们会不时更新。
        现在,由于偏移值是一个索引,并且包括它及其以下的所有索引都已被消除,因此只有向其添加一些内容才有意义。由于 fibMm2 标记了大约三分之一的数组,并且它标记的索引肯定是有效的,因此我们可以将 fibMm2 添加到 offset 并检查索引 i = min(offset + fibMm2, n) 处的元素。 

可视化: 

时间复杂度分析: 
当我们继续寻找目标时,当我们的目标位于数组的较大 (2/3) 部分时,最坏的情况就会发生。换句话说,我们每次都会消除数组中较小的 (1/3) 部分。我们对 n 调用一次,然后对 (2/3) n 调用一次,然后对 (4/9) n 调用一次,以此类推。
考虑一下:  

辅助空间: O(1)

方法 2:迭代
        斐波那契搜索是一种搜索算法,用于查找排序数组中元素的位置。斐波那契搜索的基本思想是使用斐波那契数来确定数组中的分割点,并对适当的子数组进行二分搜索。
下面是使用迭代方法的斐波那契搜索的 Javascript 实现:

// Javascript equivalent 
function fibonacci_search(arr, x) { 
    var n = arr.length; 
    if (n === 0) { 
        return -1; 
    } 
  
    // Initialize Fibonacci numbers 
    var fib1 = 0; 
    var fib2 = 1; 
    var fib3 = fib1 + fib2; 
  
    // Find the smallest Fibonacci number greater than or equal to n 
    while (fib3 < n) { 
        fib1 = fib2; 
        fib2 = fib3; 
        fib3 = fib1 + fib2; 
    } 
  
    // Initialize variables for the current and previous split points 
    var offset = -1; 
    while (fib3 > 1) { 
        var i = Math.min(offset + fib2, n - 1); 
  
        // If x is greater than the value at index i,  
        // move the split point to the right 
        if (arr[i] < x) { 
            fib3 = fib2; 
            fib2 = fib1; 
            fib1 = fib3 - fib2; 
            offset = i; 
  
            // If x is less than the value at index i,  
            // move the split point to the left 
        } else if (arr[i] > x) { 
            fib3 = fib1; 
            fib2 = fib2 - fib1; 
            fib1 = fib3 - fib2; 
  
            // If x is equal to the value at index i, return the index 
        } else { 
            return i; 
        } 
    } 
  
    // If x is not found in the array, return -1 
    if (fib2 === 1 && arr[offset + 1] === x) { 
        return offset + 1; 
    } else { 
        return -1; 
    } 

  
// Driver Code 
var arr = [10, 22, 35, 40, 45, 50, 
    80, 82, 85, 90, 100,235]; 
var n = arr.length; 
var x = 235; 
var ind = fibonacci_search(arr, x); 
if (ind >= 0) { 
    console.log("Found at index:", ind); 
} else { 
    console.log(x,"isn't present in the array"); 

输出
发现于索引:11
        斐波那契搜索的时间复杂度为 O(log n),其中 n 是输入数组的长度。
        这是因为在算法的每次迭代中,搜索范围都会减少约 1/?,其中 ?是黄金比例(? ? 1.618)。将搜索范围缩小到单个元素所需的迭代次数大约为 log?(n),其中 log?表示自然对数。
        由于斐波那契搜索的每次迭代都需要恒定的时间,因此算法的总体时间复杂度为 O(log n)。这使得斐波那契搜索成为比线性搜索更快的算法,但比二分搜索和其他对数搜索算法(例如插值搜索和指数搜索)慢。
辅助空间:O(1)  

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

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

相关文章

HarmonyOS开发实例:【app帐号管理】

应用帐号管理 介绍 本示例选择应用进行注册/登录&#xff0c;并设置帐号相关信息&#xff0c;简要说明应用帐号管理相关功能。效果图如下&#xff1a; 效果预览 使用说明参考鸿蒙文档&#xff1a;qr23.cn/AKFP8k点击或者转到。 1.首页面选择想要进入的应用&#xff0c;首次进…

【Redis】持久化

文章目录 一、RDB1.1、RDB的自动备份与手动备份1.1.1、自动备份1.1.2、手动备份 1.2、RDB优点1.3、RDB缺点1.4、RDB快照1.5、RDB优化配置项 二、AOF2.1、AOF工作流程2.2、AOF写回策略2.3、MP-AOF实现2.4、AOF优缺点2.5、AOF重写机制 三、RDBAOF混合持久化3.1、数据恢复顺序和加…

生产环境中秒杀接口并发量剧增与负载优化策略探讨

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 1. 实施限流措施 1.1 令牌桶算法&#xff1a; 1.2 漏…

如何申请阿里云服务器学生优惠,入口在这呢!

阿里云学生服务器免费申请&#xff0c;之前是云翼计划学生服务器9元/月&#xff0c;现在是高校计划&#xff0c;学生服务器可以免费申请&#xff0c;先完成学生认证即可免费领取一台云服务器ECS&#xff0c;配置为2核2G、1M带宽、40G系统盘&#xff0c;在云服务器ECS实例过期之…

什么是队头阻塞以及如何解决

前言 通常我们提到队头阻塞&#xff0c;指的可能是TCP协议中的队头阻塞&#xff0c;但是HTTP1.1中也有一个类似TCP队头阻塞的问题&#xff0c;下面各自介绍一下。 TCP队头阻塞 队头阻塞&#xff08;head-of-line blocking&#xff09;发生在一个TCP分节丢失&#xff0c;导致…

ip地址切换器安卓版,保护隐私,自由上网

在移动互联网时代&#xff0c;随着智能手机和平板电脑的普及&#xff0c;移动设备的网络连接变得愈发重要。为了满足用户在不同网络环境下的需求&#xff0c;IP地址切换器安卓版应运而生。本文将以虎观代理为例&#xff0c;为您详细解析IP地址切换器安卓版的功能、应用以及其所…

26、链表-环形链表II

思路&#xff1a; 这道题就是判断链表中是否有环&#xff0c;首先使用集合肯定可以快速地解决&#xff0c;比如通过一个set集合遍历&#xff0c;如果遍历过程中有节点在set中已经存在那么说明存在环。返回这个节点即可 第二种方式就是通过快慢指针方式寻找环。如何做呢&#xf…

震惊!借助Coze白嫖GPT4-128k解决方案

震惊!某大佬借助Coze白嫖GPT4-128k解决方案 前言 此文章介绍如何免费使用GPT-4高级模型并拓展API功能 最近的 Coze 在国内开放了&#xff0c;可以免费使用大模型。但是和国外的有点区别&#xff0c;国外版本使用的chatgpt4&#xff0c;国内版本使用的是语雀大模型。 Coze是一…

《前端防坑》- JS基础 - 你觉得typeof nullValue === null 么?

问题 JS原始类型有6种Undefined, Null, Number, String, Boolean, Symbol共6种。 在对原始类型使用typeof进行判断时, typeof stringValue string typeof numberValue number 如果一个变量(nullValue)的值为null&#xff0c;那么typeof nullValue "?" const u …

图书推荐:用ChatGPT获取在线被动收入的8个方法

Universe S. The ChatGPT Money Mastery. Unlocking Online Income..for Dummies 2023 想要彻底革新您的收入模式吗&#xff1f;《用ChatGPT获取在线被动收入的8个方法》一书是您不可错过的指南。 在这个数字化飞速发展的时代&#xff0c;人工智能成为了开启成功之门的钥匙。…

2024年广东省网络系统管理样题第1套网络搭建部分

2024年广东省职业院校技能大赛样题1 信息安全管理与评估 网络系统管理 网络搭建与应用 云计算 软件测试 移动应用开发 任务书&#xff0c;赛题&#xff0c;解析等资料&#xff0c;知识点培训服务 添加博主wx&#xff1a;liuliu5488233 网络系统管理赛项 模块A&#xff1a;网络…

操作系统(第四周 第二堂)

目录 回顾 进程运行 进程的创建 进程的工作 举例 进程的删除 举例1&#xff08;走到return 0结束&#xff09; 举例2&#xff08;利用exit&#xff08;1&#xff09;结束&#xff09; 进程通信 共享内存 生产者算法 消费者算法 消息传递 定义 算法实现 总结 回顾…

数据结构--链式队列

一.链式队列的设计思想: 首先一定要理解设计的初衷,就是队头队尾的位置要满足怎么快怎么设计.那么分析如下: 最终我们敲定了入队,出队的时间复杂度都为O(1)的一种设计,也就是第四种设计;当然,头节点的数据域不使用,所以我们设计链式队列的头节点的时候删除数据域即可,链式队列…

了解虚拟路由器冗余协议(VRRP)

虚拟路由器冗余协议&#xff08;VRRP&#xff09;是一种被广泛使用的网络协议&#xff0c;旨在增强网络的可靠性和可用性。对于网络管理员和工程师来说&#xff0c;了解VRRP是确保网络能够实现无缝故障转移和保持不间断连接的关键。本文将深入探讨VRRP的基础知识&#xff0c;包…

ZooKeeper分布式服务与Kafka消息队列+ELKF整合方案

前言 ZooKeeper 是一个分布式的、开放源码的分布式应用程序协调服务&#xff0c;提供配置维护、命名服务、分布式同步、组服务等功能&#xff1b; Kafka 是一个开源的分布式流处理平台&#xff0c;它被设计用来处理实时数据流&#xff0c;包括发布和订阅消息系统、日志收集以…

leetcode经典困难题-接雨水

. - 力扣&#xff08;LeetCode&#xff09; 42. 接雨水 困难 相关标签 相关企业 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,…

单链表详解(无哨兵位),实现增删改查

1.顺序表对比单链表的缺点 中间或头部插入时&#xff0c;需要移动数据再插入&#xff0c;如果数据庞大会导致效率降低每次增容就需要申请空间&#xff0c;而且需要拷贝数据&#xff0c;释放旧空间增容造成浪费&#xff0c;因为一般都是以2倍增容 2.链表的基础知识 链表也是线…

【JavaSE进阶】00-基础语法(13-14章) 01-面向对象 02-数组 03-常用类 04-异常处理

13 第十三章 方法覆盖和多态(Polymorphism)★★★★★ 13.1 章节目标与知识框架 13.1.1 章节目标 理解在什么情况下我们需要进行方法覆盖&#xff1f;掌握在满足什么条件的时候构成方法覆盖&#xff1f;什么是多态&#xff0c;代码怎么写&#xff1f;向上转型和向下转型都是…

知云文献翻译8.2 下载地址及安装教程

知云文献翻译8.2是一款专业的文献翻译软件。它由知云公司开发&#xff0c;旨在帮助用户快速、准确地翻译各种文献和学术资料。 知云文献翻译8.2具备以下主要功能&#xff1a; 多语言翻译&#xff1a;支持多种常见的语言对&#xff0c;如中英、英中、中日、中韩等。用户可以选…

蓝桥杯DFS自练三题-串变换,玩具蛇,分糖果

题目一:串变换 代码解析: #include <iostream> using namespace std; struct Option{int select;int x;int y; }; string S,T; int N,K;//N是串的长度&#xff0c;K是操作指令的大小 Option opt[10];//存储所有的指令 bool vis[10];//标记数组&#xff0c;重要&#xff…