找到差异小于未排序数组的平均值?

时间:2008-12-15 12:12:43

标签: arrays algorithm

我需要在未排序的数组中找到2个元素,使它们之间的差异小于或等于(最大 - 最小)/(数组中元素的数量)。

在O(n)。

我知道最大值和最小值。

有人能想到什么吗?

谢谢!

3 个答案:

答案 0 :(得分:3)

第1步:使用Bucket Sort。不要对各个桶进行排序。

从这里开始应该是非常明显的,以及如何调整存储桶的大小。

答案 1 :(得分:1)

  1. 水桶数量= 2n

    每个桶中的

    值= (min + k((max-min)/2n)) <= value < (min + (k+1)((max-min)/2n)).

    0&lt; = k&lt; 2n个

    每个桶的范围= ((max-min)/2n)

  2. 将每个元素分配到存储桶中。不要在内部排序。

  3. 如果任何存储桶包含多个元素,则它们之间的最大可能差异为((max-min)/2n)。因此,你有答案。

  4. 如果任意两个连续的桶每个都有多个零元素,则它们之间的最大差异为((max-min)/2n)*2 = ((max-min)/n)。因此,你有答案。

答案 2 :(得分:1)

正确的问题应该是: 在数组A = [a0,a2,.. an]中找到两个元素a,b,使它们之间的差小于或等于:(M-m)/ n> | a-b |其中M = max(A)和m = min(A)。

我建议的解决方案是使用quickSelect,期望的时间复杂度为O(n)。实际上最糟糕的情况是O(n ^ 2)。这是一个折衷,因为大多数时候它是O(n),但是它需要O(1)空间复杂度(如果quickSelect是迭代实现的,而我的伪代码是使用while循环而不是递归实现的。)

主要思想: 在每次迭代中,我们使用quickSelect来找到中值,如果|max - medianValue | > |min - medianValue |,我们知道我们应该搜索数组的左侧。那是因为我们在两侧都有相同数量的元素,但是中值接近最小值,因此它们之间的差异应该较小。否则,我们应该在右侧搜索。

每次我们都知道子数组的新最大值或最小值应为中间值。 我们会继续搜索,每次将数组大小除以2。

运行时预期证明: 假设在n个元素上进行的每次迭代均期望值c * n + d 因此我们有:

(c n + d)+ 0.5 (c n + d)+ 0.25 (c * n + d)+…+(1 / log_ {2} (n))(c n + d)<=

<=(1 + 0.5 + 0.25 + ....)d +(c * n + 0.5 * c n + ....)=(1 + 0.5 + 0.25 + ....)d + c n(1 + 0.5 + 0.25 + ....)=

= 2 * d + 2 * c * n

意味着我们期望O(n)。

使用递归的伪代码:

run(arr):
   M = max(arr)
   m = min(arr)
   return findPairBelowAverageDiff(arr,0,arr.length,m,M)

findPairBelowAverageDiff(arr, start, end,  min,  max) :
      if start + 1 < end:
            medianPos = start + (end - start) / 2
         // median that is between start and end in the arr.
            quickSelect(arr,  start,  medianPos,  end)
            if max - arr[medianPos] > arr[medianPos] - min:
                return findPairBelowAverageDiff(arr, start, medianPos, 
                                min, arr[medianPos])
            else :
                return findPairBelowAverageDiff(arr, medianPos, 
                                        end, arr[medianPos], max);
       else :
            return (arr[start],  arr[start + 1])