【问题标题】:Binary Search of an unsorted list未排序列表的二分查找
【发布时间】:2016-02-16 06:26:27
【问题描述】:

我需要对数字列表使用二进制搜索并让它返回数字的索引。当列表未排序时,我该怎么做?我需要返回未排序列表的索引,而不是排序列表。

【问题讨论】:

  • 为什么你认为二分搜索可以在未排序的列表上工作?您可以使用线性搜索。二进制搜索就出来了。
  • 您不能对未排序的列表使用二进制搜索。您最好的选择是可能遍历列表的项目,直到找到您要查找的元素,即 O(n) 操作。
  • 为什么不用python的内置函数list.index()?根据stackoverflow.com/questions/32278255/…,比二分查找要快。

标签: python binary-search


【解决方案1】:

如果您想要未排序列表中的索引并且您使用二分查找,请尝试以下步骤:

  1. 为未排序列表中的每个项目分配一个索引
  2. 对列表进行排序
  3. 运行二分查找
  4. 返回与找到的项目关联的索引

二分搜索仅适用于已排序的列表,因此如果您需要使用该搜索算法,则无法在流程中的某个位置对其进行排序。

【讨论】:

  • 直接在未排序的列表中迭代会更快。
  • 毫无疑问,这不是最有效的方法,但如果他的任务(听起来像家庭作业)是使用二分搜索返回索引,他将不得不先对其进行排序。跨度>
  • @Johan 对于一次搜索,这是真的。随着搜索次数的增长,除了log(n),这种方法会变得更快。
  • @beaker 是的,聪明的问题是当n*k 变得大于k*log(n)+n
  • @Johan k*log(n)+n*log(n)? k 分别搜索log(n)n*log(n) 的预处理步骤进行排序?
【解决方案2】:

我认为这不是很有效的方法。我的实现在这里。

class Node(object):
   def __init__(self, index, value):
     self.index = index
     self.value = value


def binary_search(numbers, item):
    if len(numbers) == 0:
       return False
    else:
       middle = len(numbers) // 2
       if numbers[middle].value == item:
          return numbers[middle].index
       else:
          if item < numbers[middle].value:
             return binary_search(numbers[:middle], item)
          else:
             return binary_search(numbers[middle + 1:], item)

  unsorted_elems = [12, 2, 1, 5, 3, 7, 9]
  elems = []

  i = 0
  for elem in unsorted_elems:
     elems.append(Node(i, elem))
     i += 1

  elems = sorted(elems, key=lambda x: x.value)

  print(binary_search(elems, 1000)) //False
  print(binary_search(elems, 2)) // 1

【讨论】:

    【解决方案3】:

    您需要对列表的副本进行排序,并将索引列表维护回原始列表。

    一种方法是使用decorate-sort-undecorate idiom

    >>> values = [5, 2, 7]
    >>> decorated = list(zip(value, range(len(values))))
    >>> sorted_decorated = sorted(decorated)
    >>> sorted_values, indices = list(zip(sorted_decorated))
    
    >>> sorted_values
    [2, 5, 7]
    
    >>> indices
    [1, 0, 2]
    

    然后您可以对排序后的值进行二分搜索,并将索引映射回原始值。

    你可以使用bisect模块来implement binary search

    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
    

    使用它:

    >>> index(sorted_values, 5)
    1
    

    所以原来的索引是:

    >>> indices[1]
    0
    

    【讨论】:

      猜你喜欢
      • 2017-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 2013-04-01
      相关资源
      最近更新 更多