查找算法:二分查找、插值查找、斐波那契查找

news2024/11/30 8:47:02

二分查找

查找的前提是数组有序

思路分析

代码实现

# 二分查找(递归法实现)
# 找到一个相等的值就返回该值的下标
def binary_search(arr: list, find_val: int, left: int, right: int):
    mid = (left + right) // 2  # 寻找数组中间位置的下标

    if left > right:  # 找不到元素,返回-1
        return -1

    if find_val == arr[mid]:  # 找到了元素,返回元素在数组中的下标
        return mid
    elif find_val < arr[mid]:  # 要找的元素比数组中间元素小,则继续在 mid 的左边寻找
        return binary_search(arr, find_val, left, mid - 1)
    else:  # 要找的元素比数组中间元素大,则继续在 mid 的右边寻找
        return binary_search(arr, find_val, mid + 1, right)


arr = [4, 8, 9, 10, 12, 14, 15]
res = binary_search(arr, 0, 0, len(arr) - 1)
print(res)


# 二分查找(递归法实现)
# 如果数组中有多个值和要查找的值相等,则把它们的下标都返回
def binary_search2(arr: list, find_val: int, left: int, right: int):
    mid = (left + right) // 2  # 寻找数组中间位置的下标

    if left > right:  # 找不到元素,返回-1
        return []

    if find_val == arr[mid]:  # 找到了元素,返回元素在数组中的下标
        # 找到了元素,先把当前的下标放入到一个列表中
        # 再依次从该位置开始向左和向右查找,还有没有其他相等的值
        index_pos = []
        index_pos.append(mid)

        temp = mid - 1
        while True:  # 向左查找
            if temp < left or arr[temp] != find_val:
                break
            index_pos.append(temp)
            temp -= 1  # temp 左移

        temp = mid + 1
        while True:  # 向右查找
            if temp > right or arr[temp] != find_val:
                break
            index_pos.append(temp)
            temp += 1  # temp 右移

        return index_pos
    elif find_val < arr[mid]:  # 要找的元素比数组中间元素小,则继续在 mid 的左边寻找
        return binary_search2(arr, find_val, left, mid - 1)
    else:  # 要找的元素比数组中间元素大,则继续在 mid 的右边寻找
        return binary_search2(arr, find_val, mid + 1, right)


arr = [4, 8, 9, 10,10, 12, 14, 15]
res = binary_search2(arr, 0, 0, len(arr) - 1)
print(res)

插值查找

查找的前提是数组有序

思路分析

当数组为[1, 2, 3, 4, 5, ..., 100] 时,加入此时要查找1,那么二分查找的方法会进行多次递归才能找到,效率较低,所以有了插值查找方法。插值查找适用于数据比较连续的情况下。

代码实现

# 插值查找
def insert_value_search(arr: list, find_val: int, left: int, right: int):
    # 找不到元素,返回-1
    # 条件 find_val < arr[left] or find_val > arr[right] 要有,否则mid可能会越界
    if left > right or find_val < arr[left] or find_val > arr[right]:  
        return -1
    # 寻找数组中间位置的下标
    mid = left + (right - left) * (find_val - arr[left]) // (arr[right] - arr[left])
    mid_val = arr[mid]
    if find_val == mid_val:  # 找到了元素,返回元素在数组中的下标
        return mid
    elif find_val < mid_val:  # 要找的元素比数组中间元素小,则继续在 mid 的左边寻找
        return binary_search(arr, find_val, left, mid - 1)
    else:  # 要找的元素比数组中间元素大,则继续在 mid 的右边寻找
        return binary_search(arr, find_val, mid + 1, right)


arr = []
for i in range(100):
    arr.append(i + 1)
res = insert_value_search(arr, 3, 0, len(arr) - 1)
print(res)

斐波那契查找

查找的前提是数组有序

思路分析

代码实现

import copy
# 斐波那契查找
# 因为算法中需要用到斐波那契数列,所以此处用非递归的方法构造一个斐波那契数列
def fib(size: int) -> list:
    f = []
    f.append(1)
    f.append(2)
    i = 2
    while i < size:
        f.insert(i, f[i - 1] + f[i - 2])
        i += 1

    return f


# 非递归方式实现斐波那契查找算法
def fibonacci_search(arr, key):
    low = 0
    high = len(arr) - 1
    k = 0  # 表示斐波那契分割数值的下标
    mid = 0  # 存放 mid 值
    f = fib(20)  # 获取斐波那契数列
    # 获取斐波那契分割数值的下标
    while high > f[k] - 1:
        k += 1

    # 因为f[k]的值可能大于arr的长度,因此需要对数组进行扩容(新构造一个数组)
    # 让数组的长度等于f[k],新增加的长度的下标用arr数组最后的数填充
    # 如:arr=[1,8,10,89,1000,1234]  f[k] = 8
    # 扩容后:temp=[1,8,10,89,1000,1234,1234,1234]
    temp = copy.deepcopy(arr)
    i = high + 1
    while i < f[k]:
        temp.append(arr[high])
        i += 1

    # 使用 while 来循环处理,找到要查找的key
    while low <= high:  # 只要条件满足就可以继续查找
        mid = low + f[k - 1] - 1
        if key < temp[mid]:  # 应该继续向数组的前面查找(左边)
            high = mid - 1
            """
            k -= 1 说明:
            数组全部元素 = 前面(左边)的元素 + 后面(右边)的元素
            斐波那契数列:f[k] = f[k - 1] + f[k - 2]
            因为前面有f[k - 1]个元素,所以可以继续拆分:f[k - 1] = f[k - 2] + f[k - 3]
            即在f[k - 1] 的前面继续查找,即下次循环 mid = f[k - 1 - 1] - 1 
            """
            k -= 1
        elif key > temp[mid]:  # 应该继续向数组的后面查找(右边)
            low = mid + 1
            """
            k -= 2  说明:
            数组全部元素 = 前面(左边)的元素 + 后面(右边)的元素
            斐波那契数列:f[k] = f[k - 1] + f[k - 2]
            因为后面有f[k - 2]个元素,所以可以继续拆分:f[k - 2] = f[k - 3] + f[k - 4]
            即在f[k - 2] 的前面继续查找 k-=2,即下次循环 mid = f[k - 1 - 2] - 1 
            """
            k -= 2
        else:  # 找到
            # 确定返回的是哪个下标
            if mid <= high:
                return mid
            return high

    # 找不到,返回-1
    return -1


arr=[1,8,10,89,1000,1234]
res = fibonacci_search(arr, 8)
print(res)

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

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

相关文章

MySQL进阶(再论JDBC)——JDBC编程思想的分析 JDBC的规范架构 JDBC相关的类分析

前言 SQL&#xff08;Structured Query Language&#xff09;是一种用于管理关系型数据库的标准化语言&#xff0c;它用于定义、操作和管理数据库中的数据。SQL是一种通用的语言&#xff0c;可以用于多种关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;如MySQ…

自动泊车系统设计学习笔记

1 概述 1.1 自动泊车系统研究现状 目前对于自动泊车系统的研究方法通常有两种实现方式&#xff1a; 整个泊车操作可以分为四个阶段&#xff1a;第一阶段车辆向前行驶进行车位识别&#xff0c;第二阶段车辆行驶到准备泊车时的待泊车区域&#xff0c;第三阶段车辆按照规划好的…

联邦学习综述三

A Survey on Federated Learning Systems Vision Hype and Reality for Data Privacy and Protection 选自&#xff1a;IEEE Transactions on Knowledge and Data Engineering&#xff0c;2021 链接 本文主要从数据分布、机器学习模型、隐私机制、通信架构、联邦规模和联邦动…

aps.net core 6.0 web API SwaggerUI IIS部署【23.10.15】亲测,通过

目录 一、aps.net core 6.0 web API 项目配置 创建项目设置 Swagger UI 为起始页发布项目二、在 IIS 部署 安装IIS安装 Hosting Bundle三、内网穿透 使用的是 VS2022社区版&#xff0c;WebAPI的版本是 .netcore6.0 一、aps.net core 6.0 web API 项目配置 1.创建项目 运行项目…

网络层哪些事?

在本文讲解的网络层中&#xff0c;注意了解一下&#xff1a;IP协议&#xff01; 地址管理&#xff1a;每个网络上的设备&#xff0c;要能分配一个地址&#xff08;唯一&#xff09;路由选择&#xff1a;A给B发消息&#xff0c;具体走哪条路线&#xff1f;&#xff1f; IP地址&…

kube-controller-manager和kube-scheduler不能正常启动

kube-controller-manager-k8s-worker01和kube-scheduler-k8s-worker01没有启动起来 原因&#xff1a; 解决&#xff1a;进入/etc/kubernetes/manifests 编辑 将镜像地址修改为 然后重启kubelet&#xff1a;systemctl restart kubelet.service

JVM 垃圾回收机制(可达性分析、引用计数)

目录 1 什么是垃圾2 为什么需要回收3 哪些对象被判定为垃圾呢3.1 引用计数法3.2 可达性分析算法&#xff1a;GC Roots根 1 什么是垃圾 垃圾是指在运行程序中没有任何指针指向的对象&#xff0c;就是需要被回收的。 2 为什么需要回收 执行程序会不断地分配内存空间&#xff0c…

快速上手 vue3

快速上手 vue3 文章目录 1. 组合式 api2. 路由3. 定义全局方法和变量4. 父子组件调用 --> 自定义事件5. 生命周期函数6. 状态管理 vuex 1. 组合式 api setuprefreactivecomputed生命周期钩子 , onMounted … 2. 路由 安装路由: npm install vue-router 创建一个 router…

欠拟合、过拟合及优化:岭回归

问题:训练数据训练的很好啊,误差也不大,为什么在测试集上面有问题呢? 当算法在某个数据集当中出现这种情况,可能就出现了过拟合现象。 1、 什么是过拟合与欠拟合 欠拟合 过拟合 分析 第一种情况:因为机器学习到的天鹅特征太少了,导致区分标准太粗糙,不能准确识别出天鹅…

基于SSM的摄影约拍系统

基于SSM的摄影约拍系统的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatisJSP工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 前台系统&#xff1a;首页拍摄作品展示、摄影师展示、模特展示、文章信息、交流论…

【Java学习之道】线程的生命周期与状态转换

引言 多线程编程是Java程序员必备的技能之一&#xff0c;它可以让我们的程序更加高效地运行。在学习多线程编程时&#xff0c;我们需要了解线程的生命周期和状态转换。本篇文章将为你揭示线程的奥秘&#xff0c;让你轻松掌握多线程编程的基础知识。 一、线程的生命周期 线程…

解码自然语言处理之 Transformers

自 2017 年推出以来&#xff0c;Transformer 已成为机器学习领域的一支重要力量&#xff0c;彻底改变了翻译和自动完成服务的功能。 最近&#xff0c;随着 OpenAI 的 ChatGPT、GPT-4 和 Meta 的 LLama 等大型语言模型的出现&#xff0c;Transformer 的受欢迎程度进一步飙升。这…

【LeetCode刷题(数据结构与算法)】:平衡二叉树

给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true 输入&#xff1a;roo…

SpringMVC全注解开发

在学习过程中&#xff0c;框架给我们最大的作用&#xff0c;就是想让开发人员尽可能地只将精力放在具体业务功能的实现之上&#xff0c;而对于各种映射关系的配置&#xff0c;统统由框架来进行完成&#xff0c;由此&#xff0c;注解就很好的将映射功能进行实现&#xff0c;并且…

CentOS-7网卡重启后关闭的解决方法

第一步查找网卡&#xff1a; ip addr 如下图&#xff1a; 于是发现网卡eth0。 第二步进入网卡配置目录并进行配置&#xff1a; cd /etc/sysconfig/network-scriptsvim ifcfg-eth0 第三步改配置如下图&#xff1a; 然后每次重启后网卡会自动启动。

网络基础2(1)

HTTP 1.应用层协议2.send和recv单独使用不安全3.URL4.urlencode和urldecode5.HTTP协议格式6.HTTP中的常见请求方法POST&&GET7.HTTP的状态码8.HTTP常见Header &#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f6…

【算法|前缀和系列No.1】牛客网 DP34 【模板】前缀和

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【牛客网刷题】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希…

Opencv——颜色模型+通道分离与合并

视频加载/摄像头调用 VideoCapture允许一开始定义一个空的对象 VideoCapture video VideoCapture(const String &filename,int apiPreferenceCAP_ANY) filename:读取的视频文件或者图像序列名称 apiPreference:读取数据时设置的属性&#xff0c;例如编码格式、是否调用Op…

罗技鼠标接收器丢失或损坏后用另一个接收器配对的方法

本文介绍罗技鼠标在丢失、损坏其自身原有的接收器后&#xff0c;将另一个新的接收器与原有鼠标相互配对的方法。 在开始之前&#xff0c;大家需要首先查看两个内容&#xff1a;首先是原有的鼠标——大家需要查看自己的鼠标&#xff08;罗技键盘也是同样的操作&#xff09;底部&…

【动态规划】309. 买卖股票的最佳时机含冷冻期、 714. 买卖股票的最佳时机含手续费

提示&#xff1a;努力生活&#xff0c;开心、快乐的一天 文章目录 309. 买卖股票的最佳时机含冷冻期&#x1f4a1;解题思路&#x1f914;遇到的问题&#x1f4bb;代码实现&#x1f3af;题目总结 714. 买卖股票的最佳时机含手续费&#x1f4a1;解题思路&#x1f914;遇到的问题&…