Python中反向排序列表的二进制搜索

时间:2015-03-14 03:37:07

标签: python binary-search

如果列表按升序排序,使用bisect模块,已经有一个关于如何在Python中进行二进制搜索的主题:Binary search (bisection) in Python

有没有一种好方法可以对反向排序的列表进行二进制搜索?

2 个答案:

答案 0 :(得分:3)

这是documentations所说的:

  

与sorted()函数不同,bisect()函数具有关键或反向参数没有意义,因为这会导致设计效率低下(连续调用bisect函数不会“记住”以前的所有函数密钥查找)。

因此它不支持自定义订单。任何绕过它的尝试(例如将列表反转两次,或者准备一个单独的键列表)都会花费线性时间,这完全破坏了二元搜索的点,这是对数的。

这是一个接受比较器的二进制搜索的实现

def bisect(arr, val, cmp):
    l = -1
    r = len(arr)
    while r - l > 1:
        e = (l + r) >> 1
        if cmp(arr[e], val): l = e
        else: r = e
    return r

如果您需要bisect_right,它最后的行为类似于return lbisect_left。以下是反向数组的示例用法:

>>> a = [10**8 - x for x in range(10**8)]
>>> bisect(a, 100, lambda x, y: x > y)
99999900

答案 1 :(得分:0)

在这种情况下,使用代码段来复制库函数是有益的,例如bisect_leftbisect_right。通过将<(或<=)更改为>(或>=),可以对等式搜索降序数组。

def bisect_left(a, x, lo=0, hi=None):
    if hi is None: hi = len(a)
    while lo < hi: 
        mid = (lo + hi)//2
        if a[mid] < x: lo = mid + 1
        else: hi = mid 
    return lo

def bisect_right(a, x, lo=0, hi=None):
    if hi is None: hi = len(a)
    while lo < hi: 
        mid = (lo + hi)//2
        if a[mid] <= x: lo = mid + 1
        else: hi = mid
    return lo