查找失败的平均查找长度怎么求_插值查找

79a3b3c847e882b73f0d99968ee65d24.png

查字典

当我们从字典中查找 “algorithm” 这个单词的时候,我们肯定不会傻傻地像二分查找一样首先从中间开始。相反,我们会从首字母为 a 的地方开始查找,然后根据第二个字母在字母表中的位置,找到相应的位置再继续查找,这样重复这个过程,直到我们查找到这个单词。

接下来我们就来介绍一下类似于上述过程的插值查找。

插值查找

插值查找interpolation search)实际上是二分查找的改良版。假设有这样一个数组

equation?tex=+%5B0%2C+10%2C+20%2C+30%2C+40%2C+50%2C+60%2C+70%2C+80%2C+90%5D ,我们可以发现,每个相邻元素的差均为
equation?tex=10 ,满足
均匀分布。如果要查找元素
equation?tex=70 ,我们首先可以计算数组中小于等于 70 的元素占所有元素的比例的期望值
equation?tex=p+%3D+%5Cfrac%7B%2870+-+0%29%7D%7B%2890+-+0%29%7D+%3D+%5Cfrac%7B7%7D%7B9%7D ,而数组的长度
equation?tex=n 我们知道等于
equation?tex=10 ,所以我们期望查找的索引值就为
equation?tex=%E2%8C%8An+%C3%97+p%E2%8C%8B+%3D+7 ,对应的元素为
equation?tex=70 ,恰好就是我们要找的元素。这样,原本用二分法需要查找 3 次的用插值查找只用查找 1 次,大大提高了查找的效率。

这里,我们用一个公式来表示每次查找的期望索引值:

equation?tex=x%3D%E2%8C%8A%5Cfrac%7B%28key-A%5Bl%5D%29%28r-l%29%7D%7BA%5Br%5D-A%5Bl%5D%7D%E2%8C%8B

其中,lr 分别代表数组的第一个和最后一个索引,key代表待查找的元素。

跟二分查找一样,如果一次查找失败,数组的长度就相应地减小,再代入上面的公式继续查找,直到查找成功或失败。

def formula(l, r, key, array):
    p = (key - array[l]) / (array[r] - array[l])
    n = r - l
    idx = int(n * p)
    return idx

def interpolation_search(array, key):
    l = 0; r = len(array) - 1
    while l <= r:
        m = l + formula(l, r, key, array)
        if array[m] == key:
            return m  # 查找成功
        elif array[m] < key:
            l = m + 1  # 查找右侧的数组
        else:
            r = m - 1  # 查找左侧的数组
    return -1  # 查找失败

复杂度分析

插值查找的平均复杂度为

equation?tex=%CE%98%28%5Clog+%5Clog+n%29 ,但证明过程相当的复杂,这篇
论文给出了详细的证明过程,感兴趣的同学可以自己去看看,这里我们就不再讨论了。

要是数组不是均匀分布的,插值查找的复杂度会退化到线性的复杂度

equation?tex=%CE%98%28n%29 。举一个极端的例子,假设数组为
equation?tex=%5B0%2C+99%2C+100%2C+100%2C+100%5D ,我们要查找元素
equation?tex=99 。第一轮查找我们计算出索引值为
equation?tex=3,第二轮为
equation?tex=2,第三轮为
equation?tex=1,这样我们查找了三次。推广到含有
equation?tex=n 个元素的数组就需要查找
equation?tex=n+-+2 次,所以复杂度就为
equation?tex=%CE%98%28n%29

因此,插值查找的高效性只针对均匀分布的数组,而对于分布不均匀的数组,插值查找便不再适用了。

本节全部代码

← 二分查找与二叉树 | 算法与复杂度​zhuanlan.zhihu.com
fa773540dbd9d94a1536008841003220.png
→ 归并排序 | 算法与复杂度​zhuanlan.zhihu.com
fa773540dbd9d94a1536008841003220.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值