Algorithm 如何在O(n)时间内找到向量中的最大间隙?

Algorithm 如何在O(n)时间内找到向量中的最大间隙?,algorithm,Algorithm,在高速公路的同一车道上,您可以看到不同车辆的位置,这些位置与矢量的位置相同,没有特定的顺序。如何在O(n)时间内找到相邻车辆之间的最大间隙 看起来一个简单的解决方案是先排序然后检查,但这当然不是线性的。将向量除以n+1个大小相等的桶。对于每个这样的桶,存储最大值和最小值,所有其他值都可以丢弃。由于鸽子洞原理,这些部分中至少有一部分是空的,因此这两部分中的非最小值/非最大值对结果没有影响 然后,检查铲斗,计算到下一个和上一个非空铲斗的距离,取最大值;这是最终结果 n=5且值为5,2,20,17,3

在高速公路的同一车道上,您可以看到不同车辆的位置,这些位置与矢量的位置相同,没有特定的顺序。如何在O(n)时间内找到相邻车辆之间的最大间隙


看起来一个简单的解决方案是先排序然后检查,但这当然不是线性的。

将向量除以n+1个大小相等的桶。对于每个这样的桶,存储最大值和最小值,所有其他值都可以丢弃。由于鸽子洞原理,这些部分中至少有一部分是空的,因此这两部分中的非最小值/非最大值对结果没有影响

然后,检查铲斗,计算到下一个和上一个非空铲斗的距离,取最大值;这是最终结果

n=5且值为5,2,20,17,3的示例。最小值为2,最大值为20=>铲斗尺寸为(20-2)/5=4

差异:2-5,5-17,17-20。
最大值为5-17。

我的ipc解决方案的Python实现:

def maximum_gap(l):
    n = len(l)
    if n < 2:
        return 0
    (x_min, x_max) = (min(l), max(l))
    if x_min == x_max:
        return 0
    buckets = [None] * (n + 1)
    bucket_size = float(x_max - x_min) / n
    for x in l:
        k = int((x - x_min) / bucket_size)
        if buckets[k] is None:
            buckets[k] = (x, x)
        else:
            buckets[k] = (min(x, buckets[k][0]), max(x, buckets[k][1]))
    result = 0
    for i in range(n):
        if buckets[i + 1] is None:
            buckets[i + 1] = buckets[i]
        else:
            result = max(result, buckets[i + 1][0] - buckets[i][1])
    return result

assert maximum_gap([]) == 0
assert maximum_gap([42]) == 0
assert maximum_gap([1, 1, 1, 1]) == 0
assert maximum_gap([1, 2, 3, 4, 6, 8]) == 2
assert maximum_gap([5, 2, 20, 17, 3]) == 12
def最大间隙(l):
n=len(l)
如果n<2:
返回0
(x_最小,x_最大)=(最小(l),最大(l))
如果x_min==x_max:
返回0
bucket=[None]*(n+1)
铲斗尺寸=浮动(x_最大值-x_最小值)/n
对于l中的x:
k=int((x-x_最小值)/桶大小)
如果桶[k]为无:
桶[k]=(x,x)
其他:
桶[k]=(最小(x,桶[k][0]),最大(x,桶[k][1]))
结果=0
对于范围(n)中的i:
如果桶[i+1]为无:
桶[i+1]=桶[i]
其他:
结果=最大值(结果,存储桶[i+1][0]-存储桶[i][1])
返回结果
断言最大间隔([])==0
断言最大间隔([42])==0
断言最大间隔([1,1,1,1])==0
断言最大间隔([1,2,3,4,6,8])==2
断言最大间隔([5,2,20,17,3])==12
对于bucket的元素,我使用一个
tuple
,如果为空,则使用
None
。在最后一部分中,我通过将剩余的空bucket分配给前一个bucket(这是可行的,因为第一个bucket保证为非空的)


注意所有元素相等时的特殊情况。

O(n)时间和多少空间?其中(n)是向量中的元素数?是的,这可以用一个很好的基本循环来完成。@ MatsPetersson -但是他要求一个漂亮的C++循环。@ Matts中的邻居不是公路上的邻居,它没有排序。它似乎不可能在一次迭代中轻松完成?我不能完全遵循。你介意再详细一点吗?向量应该如何划分为n+1部分?所有部分的大小都应该相同。你的意思是“取最大值和最小值,创建n+1个桶-第i个桶负责一个段[i*(max-min)/(n+1),(i+1)*(max-min)/(n+1)],这太让我难以理解了-D
def maximum_gap(l):
    n = len(l)
    if n < 2:
        return 0
    (x_min, x_max) = (min(l), max(l))
    if x_min == x_max:
        return 0
    buckets = [None] * (n + 1)
    bucket_size = float(x_max - x_min) / n
    for x in l:
        k = int((x - x_min) / bucket_size)
        if buckets[k] is None:
            buckets[k] = (x, x)
        else:
            buckets[k] = (min(x, buckets[k][0]), max(x, buckets[k][1]))
    result = 0
    for i in range(n):
        if buckets[i + 1] is None:
            buckets[i + 1] = buckets[i]
        else:
            result = max(result, buckets[i + 1][0] - buckets[i][1])
    return result

assert maximum_gap([]) == 0
assert maximum_gap([42]) == 0
assert maximum_gap([1, 1, 1, 1]) == 0
assert maximum_gap([1, 2, 3, 4, 6, 8]) == 2
assert maximum_gap([5, 2, 20, 17, 3]) == 12