【问题标题】:Making simple autocomplete using binary search使用二进制搜索进行简单的自动完成
【发布时间】:2020-03-16 23:45:37
【问题描述】:

在元组列表中(第一个是字符串,第二个是整数),我必须使用二进制搜索找到第一个元素以输入字符串开头的所有元组。在此之前,我通过 tuple 的第一个元素对元组列表进行字典排序,然后使用二分搜索将第一个元素等于输入字符串的元组添加到新列表中。这是我的代码

def binary_search(x,list):  
    l=0
    r=len(list)-1
    while l<=r:
        m=(r-1)/2+l
        m=int(m)
        if list[m][0][0:len(x)]==x:
            return list[m]
        elif list[m][0][0:len(x)]<x:
            l=m+1
        elif list[m][0][0:len(x)]>x:
            r=m-1
    return -1

然后我将我想要的元组列表添加到新列表中

new_list=[]
s=input()
lexicographic_sort(list) #function that sorts using lambda
a=binary_search(s,list)
while a!=-1:
    new_list.append(a)
    list.remove(a)
    a=binary_search(s,list)

print(new_list)

问题是当我只输入 1 个字符时,我得到了我想要的结果,但是输入超过 1 个字符时,程序就会冻结。放置超过 1 个字符的更令人困惑的问题是,当我删除 while 循环只是为了调用一个二进制搜索时,它会返回一个元组,所以我不知道为什么我的程序会冻结。
名单是[('school', 312), ('bus', 421), ('scheme', 53), ('and', 423), ('maybe', 143), ('schemes', 53), ('ands', 423), ('maybes', 143), ('schemess', 53), ('andsss', 423), ('maybesss', 143)] 输入 1:sc
输出:[('schemess', 53), ('school', 312), ('scheme', 53), ('schemes', 53)]
输入 2:可能
输出:(冻结)

【问题讨论】:

  • 你能发布一个非常小的输入,用于复制目的吗?还要检查这篇文章中的变量名是否有错误。
  • 就像@KennyOstrom 所说,我希望看到一个输入。这个对我有用。我将lexicographic_sort 定义为:def lexicographic_sort(list): list.sort(key=lambda x: x[0])
  • 抱歉,没看懂,我马上贴出来。
  • 它适用于该数据,并且 s = 'bu' 或 s = 'sc' 无法重现。如果我仅通过执行样本数据 * 10 来列出非常长的列表,它仍然有效。您在等待输入吗?最好不要使用“list”作为变量名,因为这也是一个类名。
  • 能够在list = [('school', 312), ('bus', 421), ('scheme', 53), ('and', 423), ('maybe', 143),('school', 312), ('and', 423)] 卡在elif list[m][0][0:len(x)]&gt;x: 的情况下重现

标签: python binary-search


【解决方案1】:

在二分搜索中,一个主要步骤是查看中间元素,如https://en.wikipedia.org/wiki/Binary_search_algorithm(以及其他地方)中所述

m = (r+l) // 2

你有

m=(r-1)/2+l

例如,9 和 11 的中间是 10/2+9 = 14。这是不对的。这可能会导致您查看对于数组来说太大的索引,从而使用 IndexError 退出程序。

您需要使用 // 来保证整数结果。在这种情况下,需要向下舍入。

不过,确实应该很清楚你得到了一个 IndexError 异常。不知道怎么回事,据说它冻结了。那部分没有意义。

【讨论】:

    【解决方案2】:

    应该计算“移动中间”元素m=(r-l)/2+l,但你有m=(r-1)/2+l

    应该是:

    def binary_search(x,list):  
        l=0
        r=len(list)-1
        while l<=r:
            m=(r-l)/2+l
            m=int(m)
            if list[m][0][0:len(x)]==x:
                return list[m]
            elif list[m][0][0:len(x)]<x:
                l=m+1
            elif list[m][0][0:len(x)]>x:
                r=m-1
        return -1
    

    参考:python binary search

    【讨论】:

      【解决方案3】:

      内置排序会正确排序...不需要 lamda

      terms = sorted(terms)
      

      有一个内置的二进制搜索排序列表...

      import bisect
      idx = bisect.bisect(ordered_list_to_search,term)
      print("Found: ",idx)
      

      所以你可以说(因为看起来所有数值都大于或等于 1)

      idx = bisect.bisect_right(terms,(search_term,0))
      if idx < len(terms):
          print(terms[idx])
      print("Nothing found...")
      

      【讨论】:

        猜你喜欢
        • 2015-04-10
        • 2012-06-03
        • 1970-01-01
        • 2012-01-14
        • 2012-07-29
        • 2019-06-28
        • 1970-01-01
        • 2017-09-22
        • 1970-01-01
        相关资源
        最近更新 更多