【算法系列 | 11】深入解析查找算法之—插值查找

news2024/9/25 13:16:12

序言

心若有阳光,你便会看见这个世界有那么多美好值得期待和向往。

决定开一个算法专栏,希望能帮助大家很好的了解算法。主要深入解析每个算法,从概念到示例。

我们一起努力,成为更好的自己!

今天第11讲,讲一下查找算法的—插值查找算法

一、基础介绍

查找算法是计算机科学中的一类算法,用于在数据集中寻找特定值或数据项。

其目标是确定数据是否存在于给定的数据结构中,并找到数据项的位置(索引)或其他相关信息。

不同的查找算法适用于不同类型的数据结构,数据有序性,以及数据规模。以下是一些常见的查找算法

以下是一些常见的查找算法及其应用场景:

  • 布隆过滤器(Bloom Filter):适用于判断一个元素是否存在于一个大规模的数据集中,时间复杂度为O(1),但有一定的误判率。

  • 二分查找(Binary Search):适用于有序数组中查找元素,时间复杂度为O(log n);

  • 哈希表查找(Hash Table):适用于快速查找和插入元素,时间复杂度为O(1),但需要额外的存储空间;

  • 线性查找(Linear Search):适用于无序数组中查找元素,时间复杂度为O(n);

  • 插值查找(Interpolation Search):适用于有序数组中查找元素,时间复杂度为O(log log n),但是对于分布不均匀的数据集效果不佳;

  • 斐波那契查找(Fibonacci Search):适用于有序数组中查找元素,时间复杂度为O(log n),但需要额外的存储空间;

  • 树表查找(Tree Search):适用于快速查找和插入元素,时间复杂度为O(log n),但需要额外的存储空间;

  • B树查找(B-Tree):适用于大规模数据存储和查找,时间复杂度为O(log n),但需要额外的存储空间;

一、算法介绍

1.1 原理介绍

插值查找是一种改良版的二分查找算法,其基本原理是根据要查找的值在有序数组中的大致位置进行估计,以此来缩小搜索范围,从而提高查找效率。

插值查找的核心思想是通过数据的分布情况来预测目标值的位置,从而更快地逼近目标。

特别适用于有序且均匀分布的数据集

插值查找的实现步骤

插值查找的实现步骤相对简单,主要包括以下几个步骤:

a. 计算插值位置

首先,通过插值公式计算目标值在数组中的估计位置:

其中,low[low ]和 high[high]分别是数组的起始位置和结束位置,array[low] 和 array[high] 分别是对应位置的元素值。

b. 判断目标值位置

比较目标值与估计位置的大小关系,决定在左半部分还是右半部分继续查找。

c. 递归或迭代

根据比较结果,继续在选定的半部分进行插值查找,直到找到目标值或确定目标值不存在。

1.2 优缺点

优点:

  • 适用于均匀分布的数据集: 插值查找在数据集均匀分布时效果更为显著,能够更准确地估计目标值的位置。

  • 相对于二分查找的改进: 在某些情况下,插值查找的效率较二分查找更高,尤其是对于近似均匀分布的数据。

缺点:

  • 对于不均匀分布的数据效果不佳: 当数据分布不均匀时,插值查找的性能可能较差,甚至不如二分查找。

  • 可能导致溢出: 在计算插值位置时,由于分母可能为零,导致除法溢出的风险。

1.3 复杂度

插值查找的时间复杂度主要取决于查找的数据分布情况,但最坏情况下的时间复杂度仍然是 O(log n)。下面是插值查找的复杂度的详细解释:

  1. 最好情况时间复杂度:O(1) 如果你运气好,目标元素恰好在数组的中间位置,此时插值查找的时间复杂度为常数级别,即 O(1)。这种情况下,插值查找的效率最高。

  2. 平均情况时间复杂度:O(log log n) 到 O(log n) 在平均情况下,插值查找的时间复杂度在 O(log log n) 到 O(log n) 之间。这是因为插值查找适用于均匀分布的数据,能够更准确地估计目标值的位置。在每一步查找中,搜索范围都会迅速减半,类似于二分查找。

  3. 最坏情况时间复杂度:O(n) 最坏情况下的时间复杂度为 O(n),通常发生在数据分布不均匀的情况下。如果数据分布不均匀,插值查找可能会导致多次不必要的递归或迭代,使得时间复杂度增加。

总体来说,插值查找在数据分布较为均匀的情况下性能较好,但在不均匀分布的情况下可能退化为线性查找。

因此,在选择查找算法时,需要根据实际数据分布情况权衡算法的优缺点。插值查找的优势在于能够更好地适应均匀分布的数据,但在不确定数据分布情况时,二分查找等算法可能更稳定。

1.4 使用场景

插值查找适用于数据集较大且分布相对均匀的情况,例如在数字、日期等有序数据的查找中表现较好。

在这些场景下,插值查找能够更准确地估计目标值的位置,从而提高查找效率。

1.5 拓展

可以用更简单的语言来解释插值查找算法的原理。

比方说你在一本按照字母顺序排列的电话簿中找人的电话号码。

  1. 常规查找(比如二分查找): 你会打开电话簿的中间,看这个名字是在中间的上面还是下面。然后根据比较的结果,再在剩下的一半中间找。

  2. 插值查找: 插值查找不是简单地在中间找,而是像“猜谜底”一样,通过一些估算,去猜测名字更可能在哪。比如,如果你要找的名字离电话簿的开头近,插值查找就猜测他可能在电话簿的前面。然后,你再根据这个猜测去找。

为什么这样做更快呢?🤔

假如电话簿中的名字是均匀分布的,你可以更准确地猜测名字的位置。就好比你知道字母表中的字母是均匀分布的,你可以更快地找到某个字母的位置。

总的来说,插值查找是一种更智能的查找方法,通过估算目标的位置,可以更快地找到你要找的东西。

二、代码实现

2.1 Java代码实现

2.1.1 代码示例

public class InterpolationSearch {

    public static int interpolationSearch(int[] array, int target) {
        int low = 0;
        int high = array.length - 1;

        while (low <= high && target >= array[low] && target <= array[high]) {
            // 使用插值公式计算估计位置
            int pos = low + ((target - array[low]) * (high - low)) / (array[high] - array[low]);

            if (array[pos] == target) {
                return pos; // 找到目标值,返回位置
            } else if (array[pos] < target) {
                low = pos + 1; // 在右半部分查找
            } else {
                high = pos - 1; // 在左半部分查找
            }
        }

        return -1; // 目标值不存在
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20};
        int target = 12;

        int result = interpolationSearch(array, target);

        if (result != -1) {
            System.out.println("目标值 " + target + " 在数组中的位置是:" + result);
        } else {
            System.out.println("目标值 " + target + " 未在数组中找到。");
        }
    }
}

2.1.2 代码详解

  1. interpolationSearch 方法是插值查找的实现,接受一个有序数组 array 和目标值 target 作为参数。

  2. lowhigh 分别表示数组的起始和结束位置。

  3. 使用 while 循环进行查找,确保目标值在数组范围内。

  4. 插值公式计算估计位置 pos,并根据与目标值的比较确定在左半部分还是右半部分继续查找。

  5. 如果找到目标值,返回它在数组中的位置;如果未找到,返回 -1。

  6. main 方法演示了如何使用插值查找算法来查找目标值在数组中的位置。

2.1.3 运行结果

目标值 12 在数组中的位置是:6

  • 目标值 12 在给定的有序数组 {1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20} 中的位置是索引 6

  • 因此,输出结果表示目标值 12 在数组中的位置为 6

2.2 Python代码实现

2.2.1 代码示例

def interpolation_search(array, target):
    low = 0
    high = len(array) - 1

    while low <= high and array[low] <= target <= array[high]:
        # 使用插值公式计算估计位置
        pos = low + ((target - array[low]) * (high - low)) // (array[high] - array[low])

        if array[pos] == target:
            return pos  # 找到目标值,返回位置
        elif array[pos] < target:
            low = pos + 1  # 在右半部分查找
        else:
            high = pos - 1  # 在左半部分查找

    return -1  # 目标值不存在


# 示例用法
array = [1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
target = 12

result = interpolation_search(array, target)

if result != -1:
    print(f"目标值 {target} 在数组中的位置是:{result}")
else:
    print(f"目标值 {target} 未在数组中找到。")

2.2.2 代码详解

  1. interpolation_search 函数是插值查找的实现,接受一个有序数组 array 和目标值 target 作为参数。

  2. lowhigh 分别表示数组的起始和结束位置。

  3. 使用 while 循环进行查找,确保目标值在数组范围内。

  4. 插值公式计算估计位置 pos,并根据与目标值的比较确定在左半部分还是右半部分继续查找。

  5. 如果找到目标值,返回它在数组中的位置;如果未找到,返回 -1。

  6. 示例用法中演示了如何使用插值查找算法来查找目标值在数组中的位置。

2.2.3 运行结果

运行这段代码将输出:

目标值 12 在数组中的位置是:6

这表示目标值 12 在给定的有序数组 [1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] 中的位置是索引 6

好啦,今天就到这里啦,下期见喽~~🙉

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

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

相关文章

kbdnso.dll文件缺失,软件或游戏报错的快速修复方法

很多小伙伴遇到电脑报错&#xff0c;提示“kbdnso.dll文件缺失&#xff0c;程序无法启动执行”时&#xff0c;不知道应该怎样处理&#xff0c;还以为是程序出现了问题&#xff0c;想卸载重装。 首先&#xff0c;先要了解“kbdnso.dll文件”是什么&#xff1f; kbdnso.dll是Win…

拒绝纸张浪费,Paperless-ngx开源文档管理系统将纸质版转换成可搜索的电子版档案

GitHub&#xff1a;GitHub - paperless-ngx/paperless-ngx: A community-supported supercharged version of paperless: scan, index and archive all your physical documents 在线演示&#xff1a;https://demo.paperless-ngx.com 官网&#xff1a;https://docs.paperless-n…

rime中州韵小狼毫 inputShow lua Filter 输入字符透传滤镜

在 rime中州韵小狼毫 inputShow lua Translator 一文中&#xff0c;我们通过 inputShow.lua 定制了 inputShow_translator&#xff0c;这使得我们的输入方案可以将用户输入的字符透传到候选列表中来。如下&#x1f447;&#xff1a; &#x1f446;上图中我们在候选列表中看到了…

关于“Python”的核心知识点整理大全58

目录 19.2.3 注销 1. 注销URL urls.py 2. 视图函数logout_view() views.py 3. 链接到注销视图 base.html 19.2.4 注册页面 1. 注册页面的URL模式 urls.py 2. 视图函数register() views.py 3. 注册模板 register.html 4. 链接到注册页面 base.html 注意 19.3 …

[Unity]实时阴影技术方案总结

一&#xff0c;Planar Shadow 原理就是将模型压扁之后绘制在需要接受阴影的物体上&#xff0c;这种方式十分高效&#xff0c;消耗很低。具体实现过程参考Unity Shader - Planar Shadow - 平面阴影。具按照自己的理解&#xff0c;其实就是根据光照方向计算片元在接受阴影的平面…

【备忘】今天写一下如何买免费证书

使用场景 使用微信支付宝支付转账时小游戏小程序接口开发时其它情况 开发中不可避免的会接触https&#xff0c;有的公司有运维去做这个事&#xff0c;有的是老板自己会搞https证书&#xff0c;咱多了解一项技术也是好事。 如何买证书 登录阿里云控制台&#xff0c;搜索ssl证…

Jenkins部署项目

一.安装jenkins 1.1进入jenkins官网下载jenkins war包&#xff0c;上传到服务器/usr/local目录。 1.2执行启动jenkins命令&#xff0c;&#xff08;注意jenkins版本需要的jdk版本&#xff09; /usr/local/java11/bin/java -Djava.awt.headlesstrue -jar /usr/local/jenkins.wa…

大文件快速传输解决办法汇总

在数据传输普及的当今时代&#xff0c;文件体量也在不断的突破它”大“的上线&#xff0c;很多企业也在面临着这类大文件快速传输的烦恼&#xff0c;而且这里面的“大”可不是一般意义的几M,几G的文件&#xff0c;它有可能上T级甚至是PB级别、TB级别的大文件&#xff0c;或者是…

使用 Docker 部署 SSCMS 内容管理系统

1&#xff09;SSCMS 介绍 官网&#xff1a;https://sscms.com/ GitHub&#xff1a;https://github.com/siteserver/cms SSCMS 基于 .NET Core&#xff0c;能够以最低的成本、最少的人力投入在最短的时间内架设一个功能齐全、性能优异、规模庞大并易于维护的网站平台。 2&#…

​如何把图片里背景的路人P掉?教你四种方法消除路人

在日常生活中&#xff0c;我们经常会遇到需要将图片中背景的路人P掉的情况。有时候&#xff0c;这些路人会破坏图片的整体美感&#xff0c;或者我们只想要图片中的某些元素&#xff0c;而路人的出现会分散注意力。那么&#xff0c;如何才能有效地将图片中的背景路人P掉呢&#…

2023我的编程之旅-地质人的山和水

引言 大家好&#xff0c;我是搞地质的。外行人有的说我们游山玩水&#xff0c;有的说我们灰头土脸&#xff0c;也有的说我们不是科学。 而我说&#xff0c;这是一门穷极一生青春&#xff0c;值得奉献的行业。这是一门贴近民生&#xff0c;又拥抱自然的学科。他的真理性在于探…

记事本在手机桌面上怎么找?手机里的记事本怎么找?

在日常生活、工作和学习中&#xff0c;我们时常需要随手记录一些重要的事项、灵感闪现的瞬间或者是待办的任务。比如&#xff0c;在超市购物前&#xff0c;列出购物清单&#xff1b;在开会时&#xff0c;记下重要的讨论点&#xff1b;在学习时&#xff0c;捕捉那一刹那的灵感。…

蓝桥圣诞树(C++)

问题描述 输入样例&#xff1a; 1 3 101 1 2 2 3 输出样例&#xff1a; YES 思路&#xff1a; 这道题还是比较好想的&#xff0c;因为它构造的二叉树是用边连接起来的&#xff0c;不是像之前一样从上到下从左到右按编号构造的&#xff0c;所以可以用邻接表来存每个点还有边&am…

Docker实战02|Namespace

在上一文《Docker实战01&#xff5c;容器与开发语言》中主要介绍了Docker的基本概念与Docker安装、Go语言安装等实战技巧。 本文继续针对Namespace技术展开讲解并利用Go语言进行实践。 本系列所有代码均已经开源。关公众号回复「Go语言实现Docker」即可获得。 目录 2.1.2 U…

如何评估 RAG 应用的质量?最典型的方法论和评估工具都在这里了

随着 LLM(Large Language Model)的应用逐渐普及&#xff0c;人们对 RAG(Retrieval Augmented Generation)场景的关注也越来越多。然而&#xff0c;如何定量评估 RAG 应用的质量一直以来都是一个前沿课题。 很显然&#xff0c;简单的几个例子的对比&#xff0c;并不能准确地衡量…

关于对物料计量单位的维护

1、业务背景 一般情况下&#xff0c;在设计产品时&#xff0c;明确了物料的计量单位&#xff0c;并在维护物料主数据时&#xff0c;维护完整单位数据。 但也有例外情况&#xff0c;例如当设计产品时&#xff0c;不明确未来的打包方式&#xff0c;不明确要维护哪些种计量单位&…

JVM虚拟机:各种JVM报错总结

错误 java.lang.StackOverflowError java.lang.OutOfMemoryError:java heap space java.lang.OutOfMemoryError:GC overhead limit exceeded java.lang.OutOfMemoryError:Direct buffer memory java.lang.OutOfMemoryError:unable to create new native thread java.lang.OutOf…

霹雳吧啦Wz《pytorch图像分类》-p2AlexNet网络

《pytorch图像分类》p2AlexNet网络基础及代码 一、零碎知识点1.过拟合2.使用dropout后的正向传播3.正则化regularization4.代码中所用的知识点 二、总体架构分析1.ReLU激活函数2.手算3.模型代码 三、训练花分类课程代码1.model.py2.train.py3.predict.py 一、零碎知识点 1.过拟…

LeetCode刷题---旋转图像

解题思路&#xff1a; 首先对主对角线两边的元素进行交换 接着走一轮遍历&#xff0c;将第1列和第n列进行交换&#xff0c;第2列和第n-1列进行交换&#xff0c;直至得到最终的矩阵。 代码实现&#xff1a; public void rotate(int[][] matrix) {//首先对主对角线的元素进行交换…

企业如何做好客户管理?有哪些关键因素?

客户管理是建立和维护客户关系的重要组成部分&#xff0c;对于企业的发展至关重要。下面就让我们来看看在做好客户管理时有哪些关键因素吧。 第一个关键因素是提供优质的客户服务。无论是线上还是线下&#xff0c;当客户需要帮助时&#xff0c;他们希望能够得到有效且及时的支持…