在非常大的数组中找到 N 个唯一随机数的最佳算法

Posted

技术标签:

【中文标题】在非常大的数组中找到 N 个唯一随机数的最佳算法【英文标题】:Best algorithm to find N unique random numbers in VERY large array 【发布时间】:2015-05-14 15:46:25 【问题描述】:

我有一个数组,例如,1000000000000 个元素(整数)。例如,从该数组中仅选择 3 个随机且唯一的元素的最佳方法是什么?元素在整个数组中必须是唯一的,而不是在 N 个(在我的示例中为 3 个)元素的列表中。

我阅读了有关 Reservoir 采样的信息,但它只提供了选择随机数的方法,随机数可能是非唯一的。

【问题讨论】:

我不确定这就是你要找的,但你能不能只选择 3 个随机数,如果它们相等,请选择另一个? 我相信 Guy 是在 3 个随机数之后,这些随机数在整个数组中是唯一的。 元素在数组中必须是唯一的,而不是在 3 个元素的样本中。 所以减少问题:首先找到唯一值,然后在其中随机选择。 你的整数有多大?您可以在 O(N) 中通过在 MAXINT 空间中计算每个值的实例来完成。 【参考方案1】:

如果达到非唯一值的几率很低,最好的办法是从数组中选择 3 个随机数,然后对照整个数组检查每个数以确保它是唯一的 - 如果不是,请选择另一个随机样本替换它并重复测试。

如果达到非唯一值的几率很高,这会增加您需要扫描数组以寻找唯一性的次数,并使简单的解决方案不是最优的。在这种情况下,您需要将确保唯一数字的任务与进行随机选择的任务分开。

对数组进行排序是查找重复项的最简单方法。大多数排序算法都是 O(n log n),但由于您的键是整数,Radix sort 可能会更快。

另一种可能性是使用哈希表来查找重复项,但这需要大量空间。您可以使用较小的哈希表或Bloom filter 来识别潜在的重复项,然后使用另一种方法来遍历该较小的列表。

【讨论】:

【参考方案2】:
counts = [0] * (MAXINT-MININT+1)
for value in Elements:
  counts[value] += 1
uniques = [c for c in counts where c==1]
result = random.pick_3_from(uniques)

【讨论】:

【参考方案3】:

我假设您有一个合理的想法,即数组值的哪一部分可能是唯一的。所以你会知道,例如,如果你选择了 1000 个随机数组值,那么其中一个是唯一的可能性很大。

第 1 步。选择 3 种随机散列算法。它们都可以是相同的算法,只是第一步要为每个算法添加不同的整数。

步骤 2. 扫描阵列。以所有三种方式对每个整数进行散列,对于每个散列算法,跟踪您获得的 X 个最低散列码(您可以为此使用优先级队列),并保留每个整数出现次数的散列表。

第 3 步。对于每个哈希算法,在该存储桶中查找唯一元素。如果它已经在另一个桶中被拾取,请找到另一个。 (应该是罕见的边界情况。)

这是您的三个随机独特元素的集合。每个独特的三元组都应该有被选中的偶数几率。

(注意:对于许多目的,只使用一种哈希算法并从其列表中找到 3 个东西就可以了...)

这个算法在一次通过数组时很有可能成功。更好的是,它使用的中间数据结构相当小并且可以合并。因此,对于非常大的数据集,这可以跨机器并行化。

【讨论】:

以上是关于在非常大的数组中找到 N 个唯一随机数的最佳算法的主要内容,如果未能解决你的问题,请参考以下文章

选择随机行PostgreSQL的最佳方法

混合快速/合并排序对随机数据的性能

非常大的数组和非常大的数字的最佳编程语言?

sampleSize - 从数组中随机获取 n 个元素

在 nxn 的二维数组中查找局部最大值

Python - 优化 N 中的 2 与 N 非常大的组合