所以我试图理解二分法。我知道这是一个有用的,节省计算的算法,我得到了它的功能及其如何实现的一般概念。 我没有得到的是这个使用它的搜索功能,取自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 无论如何都检查一下......?
谢谢!
答案 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
)。