二分索引搜索 - 为何与len(a)进行比较?

时间:2016-03-29 22:46:08

标签: python bisection

所以我试图理解二分法。我知道这是一个有用的,节省计算的算法,我得到了它的功能及其如何实现的一般概念。 我没有得到的是这个使用它的搜索功能,取自https://docs.python.org/2/library/bisect.html

from bisect import bisect_left    

def index(a, x):
        'Locate the leftmost value exactly equal to x'
        i = bisect_left(a, x)
        if i != len(a) and a[i] == x:
            return i
        raise ValueError

有人可以帮我分解一下if行的 i!= len(a)部分究竟是什么?我可以读它 - 它检查x的插入索引是否等于列表a的长度 - 但我无法理解它。为什么有必要?没有它会发生什么?

我遵循这一点,假设x的插入索引大于a的长度,那么x显然不存在于a中,因此它会喷出错误 - 但如果是这种情况那么 a [i ] == x 无论如何都检查一下......?

谢谢!

2 个答案:

答案 0 :(得分:2)

由于列表是从0建立索引,因此a[i]i == len(a)没有意义(最后一个元素具有索引len(a) - 1)。对此类a[i]执行i会抛出IndexError

现在,如果bisect_left(a, x)返回len(a),则表示该元素应在列表的末尾添加,以便保留订单。

另一方面,如果x中的a匹配则

bisect_left(a, x) != len(a) 

因为If x is already present in a, the insertion point will be before (to the left of) any existing entries。如果之前的那么显然插入索引必须小于或等于最后一个索引(因为在最坏的情况下,这个匹配的元素将具有最后一个索引)和最后一个索引是len(a)-1,它小于长度。

总而言之,如果bisect_left(a, x) == len(a),则x中没有a。这使我们可以轻松摆脱我在开始时提到的“IndexError问题”。

请注意bisect_right的情况(显然)并非如此。但是,遵循类似的逻辑,您可以达到类似的效果:如果bisect_right(a, x) == 0,则x中没有a。不幸的是,通过index实施bisect_right功能会更加困难,因为您仍然需要对i == len(a)进行此检查以避免IndexError

答案 1 :(得分:0)

基于零的索引。 i != len(a)用于捕获i等于列表长度的确切情况,在这种情况下a[i]将引发索引错误(列表从索引0开始,然后转到len(a) - 1)。