在阵列中找到具有给定差异的2个项的算法

时间:2009-11-21 19:56:48

标签: algorithm language-agnostic

我得到一个实数的数组,A。它有n + 1个元素。 众所周知,阵列x和y至少有2个元素,这样:

 abs(x-y) <= (max(A)-min(A))/n

我需要创建一个算法,用于在O(n)时间内找到2个项目(如果有更多,任何一对是好的)。

我已经尝试了几个小时而且我被卡住了,有任何线索/提示吗?

2 个答案:

答案 0 :(得分:8)

哇,我明白了!诀窍在于Pigeonhole Principle.

好吧..把数字想象成一条线上的点数。然后min(A)max(A)分别定义该行的起点和终点。现在将该行划分为n等长的(max(A)-min(A))/n区间。由于有n+1个点,因此其中两个必须属于其中一个区间。

请注意,我们不需要依赖于告诉我们有两个点符合标准的问题。 总是两个点满足它。

算法本身:您可以在这里使用简化形式的桶排序,因为每个桶只需要一个项目(点击两个就完成了)。首先循环遍历数组以获取min(A)max(A),并创建一个初始化为某个默认值的整数数组buckets[n],例如-1。然后去第二遍:

for (int i=0; i<len; i++) {
    int bucket_num = find_bucket(array[i]);
    if (bucket[bucket_num] == -1)
        bucket[bucket_num] = i;
    else
        // found pair at (i, bucket[bucket_num])
}

find_bucket(x)返回x / ((max(A)-min(A))/n)的向下舍入整数结果。

答案 1 :(得分:3)

让我们重新说出问题:我们要找到两个元素,例如abs(x-y) <= c,其中c是常量,我们可以在O(n)时间找到它。 (实际上,我们可以在线性时间内计算max(A)min(A),只需指定c=(max-min)/n)。

让我们假设我们有一组桶,因此在第一个桶元素0<=x<c被放置,在第二个桶元素c<=x<=2c被放置,等等。对于每个元素,我们可以确定它的桶O(1)时间。请注意,占用的桶数不会超过数组中的元素数。

让我们迭代数组并将每个元素放到它的桶中。如果我们要放置它,那么已经存在另一个元素,那么我们刚刚找到了一对xy

如果我们迭代整个阵列并且每个元素都落入了它自己的桶中,不用担心!现在迭代存储桶(不超过n存储桶,如上所述)和每个存储桶元素x,如果在下一个存储桶y中,则{ {1}},然后我们找到了解决方案。

如果我们迭代所有的桶并找不到合适的元素,那么就没有解决方案了。 OMG,我真的很想念那些信件(见the other answer)。

存储桶可以实现为哈希映射,其中每个存储桶包含一个数组索引(在存储桶中放置元素将如下所示:abs(x-y)<=c)。我们在buckets[ a[i] / c] = i时间内计算c,在O(n)时间内将项目分配给存储桶(O(n)*O(1)是对哈希映射的访问权限),在O(1)时间内遍历存储桶。因此,整个算法是线性的。