【问题标题】:Python - Binary search being too slow and crashes computer - how can I improve the algorithmPython - 二进制搜索太慢并且计算机崩溃 - 我该如何改进算法
【发布时间】:2020-12-24 03:38:00
【问题描述】:

我一直在研究一个二分搜索问题。

不是将一个键编号与给定列表匹配,而是要求我将键列表(列表 B)与另一个列表(列表 A)匹配。如果键与列表 A 中的数字匹配,则输出应返回 A 中存在该数字的第一个索引。如果列表 A 中不存在键号,则返回 -1

假设列表 A 和列表 B 是:

A = [1, 5, 8, 12, 13]
B = [8, 1, 23, 1, 11]

由于两个列表中都存在 8,因此输出为 2,因为列表 A 中的 8 在 [2] 处。使用这个逻辑,最终的整体输出应该变成:

matched_list = [2, 0, -1, 0, -1]

下面是我的代码。如果您还可以在行内找到任何逻辑错误,将不胜感激,但是,我最关心的是运行时间。当我在计算机上按 Enter 键时,需要很长时间才能处理,并且软件(我使用 VS Code)最终崩溃了。

我有 16GB RAM 和 Intel Core i7,所以拖累它的不应该是设备,而是算法。

def binary_search(A, B, n):
# We match the numbers in key list, B, to the numbers in A

    low, high = 0, n-1
    # low limit is initialised to A[0], the first number of list A
    # high limit initialised to the last number of the list, A[n-1]

    matched_list = []

    for i in B:
        middle = (high+low)//2

        while low <= high:
            if i > A[middle]:
                low = middle+1 

            elif i < A[middle]:
                high = middle-1 
            
            else:
                matched_list.append(middle)
    
        if low > high:
            return(-1)

    return(matched_list)

A = [1, 5, 8, 12, 13]
B = [8, 1, 23, 1, 11]
n = 5  # this is the length of list A


print(binary_search(A, B, n))

有没有办法改进我的算法?

【问题讨论】:

    标签: python algorithm binary-search


    【解决方案1】:

    我修复了函数中的错误。看这段代码:

    def binary_search(A, B, n):
        matched_list = []
    
        for i in B:
            low, high = 0, n - 1
            while low <= high:
                middle = (high + low) // 2
                if i > A[middle]:
                    low = middle + 1
                elif i < A[middle]:
                    high = middle - 1
                else:
                    matched_list.append(middle)
                    break
    
            if low > high:
                matched_list.append(-1)
    
        return matched_list
    

    【讨论】:

    • 啊,谢谢,所以程序没有停止的原因是我忘了打破循环。现在说得通了。并感谢您修复其他错误
    【解决方案2】:

    在您的代码中,

    while low <= high:
                if i > A[middle]:
                    low = middle+1 
    
                elif i < A[middle]:
                    high = middle-1 
                
                else:
                    matched_list.append(middle)
    

    else 语句不会中断,因此它会陷入无限循环。添加break 语句即可解决。
    建议:由于地图/字典往往更快,您可以在O(N)而不是O(NlogN)中使用它们来有效地解决这个问题。

    【讨论】:

    • 我现在看到了我的问题,谢谢你提醒我那个循环。所以我的程序从未停止并输出答案的原因是我没有破坏它......是的,我会看看地图进行改进
    【解决方案3】:

    第一个 - 如果空间未排序,则不能使用二进制搜索。

    第二 - 如果你想要更好的算法使用地图,复杂性将是线性的

    3rd - 如果你想使用二分搜索,你可以很容易地在 set 中插入你的值,然后用 lower_bound 找到答案。

    【讨论】:

      【解决方案4】:

      @cliff_leaf,在您的情况下,使用 dict() 将数字索引保存在字典中以便 B 稍后进行快速 O(1) 查找会更容易: (二分搜索可能不适合这种情况。)您可以调整代码以在找到第一个匹配数字时中断/退出 - 8 并停止,如果这是您想要的 - 找到第一个匹配项。

      >>> A = [1, 5, 8, 12, 13]
      >>> B = [8, 1, 23, 1, 11]
      >>> aa = {n: i for i, n in enumerate(A)}
      >>> aa
      {1: 0, 5: 1, 8: 2, 12: 3, 13: 4}
      >>> for n in B:
          if n in aa: print(aa[n])
      
          
      2
      0
      0
      

      【讨论】:

      • 哇,老实说,我从来没有想过这样的算法。字典和枚举功能,我将看看这些并在我的程序中实现这些功能。谢谢
      • 很高兴它可以提供帮助。想点赞我的帖子吗?
      • 我想我已经这样做了,也许系统很慢
      猜你喜欢
      • 2012-03-19
      • 2022-10-06
      • 1970-01-01
      • 2022-11-25
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多