【问题标题】:Finding difference less than the average in an unsorted array?在未排序的数组中找到小于平均值的差异?
【发布时间】:2008-12-15 12:12:43
【问题描述】:

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

在 O(n) 中。

我知道最大值和最小值。

谁能想到点什么?

谢谢!

【问题讨论】:

  • @Binary Worrier:它有什么不同? ;-)
  • @splattne 很多,但至少意味着重新标记
  • @Greg Dean:哦,这就是区别! ;-)
  • @Splattne:我的部分工作是指导不同级别的初级程序员。仅仅提供一个完整的答案对学习者没什么好处。如果是家庭作业,我会就如何解决问题提供有用的建议,而不是给出完整的解决方案。另外 +1 Greg Dean,应该重新标记
  • 所以,可以自己更正标题“差异”和其他拼写错误。那时没有人会理解我的“有趣”评论。 ;-)

标签: arrays algorithm


【解决方案1】:

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

应该很明显从这里开始做什么,以及如何调整存储桶的大小。

【讨论】:

  • 这是正确的解决方案。我不确定“非常明显”,要担心的一件事是要检查两种情况:一种是一个皮江洞有多个皮江,另一种是所有皮江洞都正好有 1 个皮江。
  • Sid Datta 详细介绍。
【解决方案2】:
  1. 桶数 = 2n.

    每个桶中的值 = (min + k((max-min)/2n)) <= value < (min + (k+1)((max-min)/2n)).

    0

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

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

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

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

【讨论】:

  • 这行得通,虽然你可以使用 n 个桶,但你只需要比较连续的值。
  • 我认为这在某些情况下会错过解决方案。如果 n 个项目出现在交替的桶中怎么办,所以永远不会有两个连续的非空桶,但是桶 j 的“顶部”附近有一个值,而桶 j+2 的“底部”附近有另一个值。它们之间的距离小于 (max-min)/n。
  • 正如 Jimmy 所说,在这种情况下,存储桶已经对数组进行了完全排序,这意味着您可以通过 O(n) 完成以找到解决方案或证明没有解决方案。
【解决方案3】:

正确的问题应该是: 在数组 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 为期望值。 因此我们有:

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

n +….) = (1+0.5+0.25+….)d + cn(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])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    相关资源
    最近更新 更多