【问题标题】:How to find a value closest to another value X in a large sorted array efficiently如何有效地在大型排序数组中找到最接近另一个值 X 的值
【发布时间】:2016-07-08 16:14:28
【问题描述】:

对于一个排序列表,我如何找到与给定数字接近的最小数字?

例如,

mysortedList = [37, 72, 235, 645, 715, 767, 847, 905, 908, 960]

如何快速找到小于等于700的最大元素? (如果我有 1000 万个元素,那么线性搜索会很慢)。在这个例子中,答案是 645。

【问题讨论】:

标签: python search


【解决方案1】:

手动实现二分查找

def find_largest_less_than(l, max_val, lo=0, hi=None):
    if hi is None:
        hi = len(l)

    if lo > hi: return None
    if hi - lo == 1: return None if max_val < l[lo] else l[lo]

    mid = lo + ((hi - lo) // 2)
    mid_val = l[mid]

    if max_val > mid_val:
        val = find_largest_less_than(l, max_val, mid, hi)
    elif max_val < mid_val:
        val = find_largest_less_than(l, max_val, 0, mid)

    return val

mysortedList = [37, 72, 235, 645, 715, 767, 847, 905, 908, 960]
my_max = 700

find_largest_less_than(mysortedList, my_max) # 645

【讨论】:

    【解决方案2】:

    你可以使用list comprehension:

    >>> lst = [i for i in mysortedList if i <= 700]
    >>> lst[-1]
    

    【讨论】:

    • 这将遍历列表中的所有项目,即使它在中途找到了数字。 OP 说他的列表有数百万个元素。
    • @Reti43 OP 在他的帖子中没有提到数百万个元素。我没有读过cmets。我的错!
    • 不用担心。出于这个确切原因,我的评论只是为了引起您的注意。
    • @Reti43 谢谢!我很感激。
    【解决方案3】:

    您可以使用bisect 模块:

    import bisect
    
    data = [37, 72, 235, 645, 715, 767, 847, 905, 908, 960]
    
    location = bisect.bisect_left(data, 700)
    
    result = data[location - 1]
    

    这是标准库中的一个模块,它将使用binary search 来查找所需的结果。根据您需要的确切值,您还可以使用bisect_right 而不是bisect_left

    这比遍历列表更快,因为二进制搜索算法可以跳过不包含答案的部分数据。这使得它非常适合在已知要排序的数据时找到最接近的数字。

    【讨论】:

    • 这是最快的,需要 O(log n) 时间。
    • @jayelm 是的,其他答案是 O(n) :'(
    • @JamesBuck - 我的不是
    • @cricket_007 从技术上讲,它仍然是。虽然也是 O(log n)
    • @JamesBuck 我知道你在那里做了什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 2019-01-12
    • 1970-01-01
    相关资源
    最近更新 更多