【问题标题】:Why does python's bisect_left return a valid index even if the value does not exist?为什么python的bisect_left即使值不存在也返回有效索引?
【发布时间】:2019-10-25 12:04:16
【问题描述】:

我想查找一个数字是否存在于排序数组中。直截了当,数组包含从 1 到 63 的斐波那契数。下面是斐波那契数生成器及其一些输出。

stacksize = 10000  # default 128 stack
from functools import lru_cache

@lru_cache(stacksize)
def nthfibonacci(n):
    if n <= 1:
        return 1
    elif n == 2:
        return 1
    elif n > 2:
        return nthfibonacci(n - 2) + nthfibonacci(n - 1)

 output = [nthfibonacci(k) for k in range(1,63+1)]

 # truncated output: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610,987, 
           1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368,.....]

现在我想查找 number 7 是否存在,所以我使用了以下代码 使用pythonbisection module

from bisect import bisect_left
elem_index = bisect_left(a=output, x=7, lo=0, hi=len(arr) - 1) 
# output of elem_index is  5 ????  . But it is expected to be len(output) +1, right?   
# as we know if element is not found it returns len(array) +1 

如果我只是写一个简单的二进制搜索,它会给我正确的结果,如下所示:

def binsearch(arr, key):
    # arr.sort()
    low = 0
    high = len(arr) - 1
    while low <= high:
        mid = (low + high) // 2
        if arr[mid] == key:
            return mid
        else:
            if arr[mid] < key:
                low = mid + 1
            else:
                high = mid - 1
    return -1

print(binsearch(arr, 7)) # it gives me -1 as expected

那么发生了什么?

【问题讨论】:

    标签: python python-3.x binary-search bisection


    【解决方案1】:

    如前所述,bisect_left() 只是定位列表中元素的插入点 以保持排序顺序。该文档还 shows 如何将 bisect_* 函数转换为实际查找,因此您可以使用:

    def index(lst, elem):
        i = bisect_left(lst, elem)
        if i != len(lst) and lst[i] == elem:
            return i
        return -1
    

    【讨论】:

      【解决方案2】:

      The documentation on bisect_left 解释了这种行为:

      bisect_left(...)
          bisect_left(a, x[, lo[, hi]]) -> index
      
          Return the index where to insert item x in list a, assuming a is sorted.
      

      简而言之,bisect_left(和bisect_right)会告诉您元素在哪里(如果存在),或者如果不存在则插入到哪里。

      考虑一个人为的例子。当值存在时,让我们在排序列表中搜索该值。

      l = [1, 4, 5]
      bisect.bisect_left(l, 4)
      # 1
      

      bisect_left 返回 1,因为 l[1]4。现在,重复该过程,但使用该列表中不存在的值。

      bisect.bisect_left(l, 3)
      # 1
      

      在这种情况下,l[1] 是您可以在该排序列表中找到 3 个如果存在


      这对你意味着什么?你所要做的就是修改你的函数来查询bisect_left返回的索引处的元素,

      def binary_search(items, key):
          idx = bisect_left(items, key)
          if items[idx] != key:
               return -1
      
          return idx
      

      【讨论】:

      • 现在完全有意义。所以我们可以这样做 if arr[bisect_result] != key: print("Not Found").对@cs95?
      • 如果key 大于items 中的任何值,最后一个建议将引发异常
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-08
      • 2014-05-02
      • 1970-01-01
      • 2020-06-01
      • 2020-07-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多