如果列表按升序排序,使用bisect模块,已经有一个关于如何在Python中进行二进制搜索的主题:Binary search (bisection) in Python
有没有一种好方法可以对反向排序的列表进行二进制搜索?
答案 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 l
,bisect_left
。以下是反向数组的示例用法:
>>> a = [10**8 - x for x in range(10**8)]
>>> bisect(a, 100, lambda x, y: x > y)
99999900
答案 1 :(得分:0)
在这种情况下,使用代码段来复制库函数是有益的,例如bisect_left
和bisect_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