【问题标题】:how to fix list range out of index error in this case(binary search)?在这种情况下如何修复列表范围超出索引错误(二进制搜索)?
【发布时间】:2021-09-24 22:19:02
【问题描述】:

我做了一个函数,使用二分搜索计算目标出现的次数。

但是,当我尝试以给定列表中的最后一个元素作为目标运行此函数时,它给了我“列表索引超出范围”的错误。任何人,请帮我解决这个问题。提前致谢。

def binary_occurences(arr, target):
 
    start = 0
    end = len(arr)-1
    placement = -1
    occurence = 0

    while start <= end:
        center = (start + end)//2
        if target == arr[center]:
          placement = center
          end = center - 1

        elif target < arr[center]:
            end = center - 1
        else:
            start = center + 1

    if placement == -1:
      return 'your target element is not in the list'
    else:
      while (arr[placement] == target):
        placement += 1
        occurence += 1

    return print("Element", target,"occurs", occurence, "times")
 
arr = [2,5,5,5,6,7,8,8,9,9,9,9,9,10]
target = 10
binary_occurences(arr, target)
 

IndexError: 列表索引超出范围

【问题讨论】:

  • while (arr[placement] == target): placement += 1... 你需要在那里检查placement 是一个有效的索引。
  • 你的逻辑有缺陷。如果您在(排序的)列表中对特定值进行二进制搜索并且该值存在,则找到某个事件的索引不一定是最低索引 - 即该索引之前和之后可能还有其他事件。你似乎没有试图解释这一点
  • 也许 end = center-1 可以让这个函数找到特定值的最低索引

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


【解决方案1】:

这里的问题是,一旦 arr[placement] 不等于目标,用于计算出现次数的 while 循环将跳出循环。当您搜索列表中最后一个元素的出现次数时,将列表中的 n+1 个元素与目标进行比较时会抛出越界错误。为了弥补这一点,请在查看 arr[placement] == 目标之前添加一个检查,以便放置小于 arr 的长度。由于我们使用的是逻辑运算符and,它将终止循环,因为 i+1 位置不小于长度,我们不会检查该索引。

def binary_occurences(arr, target):
     
    start = 0
    end = len(arr)-1
    placement = -1
    occurence = 0

    while start <= end:
        center = (start + end)//2
        if target == arr[center]:
          placement = center
          end = center - 1

        elif target < arr[center]:
            end = center - 1
        else:
            start = center + 1
    if placement == -1:
        return 'your target element is not in the list'
    else:
        while (placement < len(arr) and arr[placement] == target):
            placement += 1
            occurence += 1

    return print("Element", target,"occurs", occurence, "times")
 

arr = [2,5,5,5,6,7,8,8,9,9,9,9,9,10]
target = 10
binary_occurences(arr, target)

【讨论】:

    【解决方案2】:

    考虑这个实现。 bsearch() 将在整数数组中对指定值执行二进制搜索。如果找到,则返回索引,否则返回 -1。如果我们在某个偏移量处找到该值,我们会向上和向下(或者,如果您愿意,可以向左和向右)扫描,以计算任何可能的额外出现:-

    def bsearch(nums, x):
        L = 0
        R = len(nums) - 1
        while L <= R:
            m = (L + R) // 2
            v = nums[m]
            if v == x:
                return m
            if v < x:
                L = m + 1
            else:
                R = m - 1
        return -1
    
    a = [2,5,5,5,6,7,8,8,9,9,9,9,9,10]
    
    x = 9
    
    if (i := bsearch(a, x)) >= 0:
        c = 1
        for _i in range(i+1, len(a)):
            if a[_i] > x:
                break
            c += 1
        for _i in range(i-1, 0, -1):
            if a[_i] < x:
                break
            c += 1
    else:
        c = 0
    print(f'{x} occurs {c} times')
    

    不用说,列表必须排序才能工作

    【讨论】:

      猜你喜欢
      • 2021-12-03
      • 2021-01-28
      • 1970-01-01
      • 1970-01-01
      • 2019-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多