最近我在一次采访中被问到这个问题。
有N个数字,太多不适合记忆。它们分为k个数据库表(未排序),每个表都可以放入内存中。找出所有数字的中位数。
对此问题的答案不太确定。
答案 0 :(得分:8)
有一些潜在的解决方案:
有关详细信息和实施,请参阅:
http://www.fusu.us/2013/07/median-in-large-set-across-1000-servers.html
答案 1 :(得分:5)
在this wikipedia article中查看“中位数中位数”算法。
答案 2 :(得分:3)
对于中位数的中位数,您仍需要进行旋转。这是一种记忆方法。在这种情况下,您需要使用流式方法。在第一遍中,您可以找到样本的最大值和最小值。将U和L称为上限和下限。然后将候选中位数设置为U和L的平均值。通过第二遍,计算X
答案 3 :(得分:3)
假设您有一个主节点(或者能够使用共识协议从您的服务器中选择一个主节点)。主设备首先向服务器查询其数据集的大小,调用此n,以便它知道查找k = n / 2的最大元素。
然后,主服务器选择一个随机服务器,并从该服务器上的元素中查询随机元素。主设备将此元素广播到每个服务器,每个服务器将其元素分成大于或等于广播元素的元素和小于广播元素的元素。
每个服务器返回大于分区大小的主服务器,调用此m。如果这些大小的总和大于k,则主服务器向每个服务器指示忽略算法其余部分的小于设置。如果它小于k,则主设备指示忽略大于集合并更新k = k-m。如果它恰好是k,则算法终止,返回的值是在迭代开始时选择的轴。
如果算法没有终止,则从其余元素中选择一个新的随机数据开始递归。
分析:
设n为元素总数,s为服务器数。假设元素大致随机且均匀地分布在服务器之间(每个服务器具有O(n / s)元素)。在迭代i中,我们期望在每个服务器上执行O(n /(s * 2 ^ i))工作,因为每个服务器元素集的大小将大致减半(记住,我们假设元素的大致随机分布) )和O(s)在主设备上工作(用于广播/接收消息并将大小一起添加)。我们期望O(log(n / s))迭代。在所有迭代中添加这些迭代给出了O(n / s + slog(n / s))的预期运行时间,并假设s<< sqrt(n)通常就是这种情况,这变得简单(O(n / s)),这是你可能希望的最好的。
另请注意,这不仅可用于查找中位数,还可用于查找任何k值的第k个最大值。
答案 4 :(得分:1)
另一种看待这种情况的方法是回到“中位数”的定义。作者的语言各不相同,但基本上中位数是将概率分布分成两个相等部分的值。
因此,不需要花费大量精力对大量数据集进行排序,而是估算分布并找到中间数据。如上所述,对于某些分布,中位数等于均值,这是快速且容易计算的。此外,如果不需要确切答案,您可以使用经验关系:mean - mode = 3 *(mean - median)。
答案 5 :(得分:0)
以下是我要做的事情:
对数据进行抽样以获得有关分布的一般概念。
使用有关分布的信息,选择一个“桶”(范围),其大小足以获得内部中位数,并且足够小以适合内存。
一次通过(O(N))计数桶之前的数字(L1_size),在桶之后(L3_size)并将该范围内的数字放入桶(L2)。您将看到所选的桶是否包含中位数。如果不是 - 转到第2步。
使用quickselect或其他方法查找存储桶中的k =(L1_size + L2_size / 2)元素。
需要O(N)+ O(L2_size)步骤。
答案 6 :(得分:0)
我也被问到了同样的问题,我无法给出确切的答案,所以在面试后我浏览了一些有关面试的书,这就是我发现的东西。
示例:数字是随机生成的,并存储在(扩展的)数组中。怎么样 您会跟踪中位数吗?
我们的数据结构头脑风暴可能类似于以下内容:
•链接列表?可能不会。链接列表在访问和 排序数字。
•数组?也许可以,但是您已经有一个数组。你能以某种方式保留元素吗 排序?那可能很贵。让我们暂缓此操作,然后在需要时返回。
•二叉树?这是可能的,因为二叉树在排序方面做得很好。实际上,如果二叉搜索树完全平衡,则顶部可能是中位数。但是请注意,如果元素数量为偶数,则中位数实际上是平均值 中间的两个元素。中间的两个元素不能同时位于顶部。这可能是一个可行的算法,但让我们回到它上面。
•堆?堆真的很擅长基本排序并跟踪最大和最小。 这实际上很有趣-如果您有两个堆,则可以跟踪更大的堆 元素的一半和较小的一半。较大的一半保留在最小堆中,例如 表示较大的一半中的最小元素位于根。较小的一半保留在 最大堆,使得较小一半的最大元素位于根。现在,有了 在这些数据结构中,您的根有潜在的中位数元素。如果 堆的大小不再相同,您可以通过弹出来快速“重新平衡”堆 一个元素从一个堆中移出并推到另一个堆上。
请注意,您做的问题越多,对哪些数据的直觉就越发展 适用的结构。您还将开发出更精细的本能,以了解哪种方法最有用。
答案 7 :(得分:-1)
如果大概的答案是足够的,那么类似于@piccolbo的方法效果很好。我假设所有的点都是整数,但如果不是,你可以乘以十或一百或其他什么来将数据标准化为整数。对计算平均值的数据进行一次传递(算术平均值。将该数字称为临时中位数。然后对数据进行第二次传递。如果数据点小于临时中位数,则将临时中位数减1。如果数据如果数据点与临时中位数相同,则临时中位数保持不变。在数据结束后,返回临时中位数。将会发生什么临时中位数最初会不时变化,但最终会稳定在非常小的范围内,这将非常接近实际中位数。