python 数据结构与算法——搜索(查找)

线性查找

🥱

def LinearSearch(A, value):
    for idx in range(len(A)):
        if A[idx] == value:
            return idx
    return None

二分查找

迭代形式

🥱看似平平无奇

def BinarySearchIterative(A, value):
    low, high = 0, len(A)-1

    while low <= high: 
        mid = (low + high) // 2
        if A[mid] > value:
            high = mid - 1
        elif A[mid] < value:
            low = mid + 1
        else:
            return mid
    return None

实际上这段代码有 bug ?看出来了吗!估计你是看不出来的 🙃

跑个测试例子:

A = [534, 246, 933, 127, 277]
for i in A:
    print(BinarySearchIterative(A, i))
'''
0
None
2
None
None
'''

5 个数有 3 个找不到,真是奇耻大辱 😅

问题出在哪呢?

问题出在你输入的数组没排序 😅

所以函数其实没问题 😅

啰嗦一堆就是想强调一下二分查找只能用于排好序的数组 😅

递归形式

def BinarySearchRecursive(A, value, low_high=None):
    if low_high is None:
        low, high = 0, len(A)
    else:
        low, high = low_high

    if low > high or len(A) == 0:
        return None

    mid = low + (high - low) // 2

    if A[mid] > value:
        return BinarySearchRecursive(A, value, (low, mid-1))
    elif A[mid] < value:
        return BinarySearchRecursive(A, value, (mid+1, high))
    else:
        return mid

插值查找

在这里插入图片描述
假设数组中的数据分布是均匀的,那就可以通过元素值的大小预判查找的位置是在数组的前半段还是后半段,而不必死板地从中间位置开始找

比如你要从英汉词典中找 apple 这个单词,你肯定不会从词典中间开始找,而是直接锁定词典的前几页或前八分之一

def InterpolationSearch(A, value):
    low = 0
    high = len(A) - 1
    while A[low] < value and A[high] >= value:
        mid = low + int((value - A[low]) / (A[high] - A[low]) * (high - low))
        if A[mid] < value:
            low = mid + 1
        elif A[mid] > value:
            high = mid - 1
        else:
            return mid
    if A[low] == value:
        return low
    return None

插值查找与二分查找的效率对比

代码计时:python 代码计时

import time

class Timer(object):
    def __enter__(self):
        self.t0 = time.time()
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('[time spent: {time:.2f}s]'.format(time = time.time() - self.t0))

对千万数据进行逐个查找:

A = [i for i in range(10000000)]
with Timer():
    for i in A:
        InterpolationSearch(A, i)
# [time spent: 5.57s]

with Timer():
    for i in A:
        BinarySearchIterative(A, i)
# [time spent: 29.61s]

二分查找花了 30 秒, 而插值查找仅用了 6 秒 !!

事实上,插值查找的平均时间复杂度为 O ( log ⁡ ( log ⁡ n ) ) O(\log(\log n)) O(log(logn))

常见考题

1. 判断数组中是否有重复元素

解法时间空间
两重循环 n 2 n^2 n21
先排序,再遍历 n log ⁡ n n\log n nlogn1
哈希表nn
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颹蕭蕭

白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值