【问题标题】:Determine if a very large array contains duplicate确定一个非常大的数组是否包含重复项
【发布时间】:2015-05-09 12:48:11
【问题描述】:

对于一个正常大小的数组,我们可以通过排序或者使用hashset等方法来判断它是否包含重复。 但是如果我们有一个非常大的数组,比如说长度是 100 亿,我们如何确定它是否包含重复?

跟进:如果我们知道这个大数组中肯定存在一个重复,我们如何确定它是哪一个?

我的想法是使用排序,但如果有更好的方法来处理这些情况,我不会这样做。

【问题讨论】:

  • 除非您对数组中保存的数据有更多了解,否则您无法比比较排序中的O(n log n) 做得更好。如果你有办法确定物品是否有序,则只能使用比较排序,否则你需要将每个物品与其他物品进行比较,即O(n^2)
  • 请指定是 10^13(比 2015 主存大)还是 10^10(大)。答案正确所需的置信水平是多少? -> Bloom filter(另一方面,如果我们谈论的是 33 位值……)
  • 您比较的是什么类型的数据,例如字符串、数字?每个基准有多大?

标签: arrays algorithm sorting duplicates


【解决方案1】:

首先,使用这样的代码将您的数据存储到 K 个存储桶中。

files = array of K file handles
for each d in data {
    write d to files[hash(d) % K]
}
close each file

如果您选择的 K 足够大,则每个存储桶都可以轻松放入 RAM。确保选择一个好的哈希函数,否则桶将不平衡。实际代码还取决于您使用的存储系统。例如,如果您使用的是普通硬盘,则寻道成本很高,需要注意避免磁盘抖动。一种方法是尽可能多地读入 RAM 中的数据,然后对其进行 K 次迭代,每次仅附加到一个输出文件。

接下来,只需依次遍历每个存储桶,看看它是否包含任何重复项。您可以使用任何有效的算法来检测重复项。

for each f in the K files {
    data = read f into RAM
    detect duplicates in data
}

另一种解决方案是使用map-reduce framework

地图步骤将如下所示:

map(value) {
    emit(key=hash(value), value=value)
}

reduce 步骤如下所示:

reduce(key, values) {
    if there's a duplicate in values {
        emit the duplicate value.
    }
}

请注意,每个reducer 只会在存在重复或哈希冲突时看到多个值。如果你选择了一个合理的散列函数,后者将是极其罕见的。

【讨论】:

  • 在检测重复部分添加布隆过滤器怎么样?应该是一个很好的捷径,说没有。
  • 这假设了相当快的随机访问(这将是 阵列 的典型特征,并且 SSD 比 HDD、磁带、穿孔卡、石碑更可能出现这种情况……)跨度>
  • @greybeard 你是对的。我会修改我的答案,注意实际代码必须更加小心。
  • @Reactormonk 我不知道你认为布隆过滤器在哪里会有帮助。给定大量数据,布隆过滤器将检测到几乎概率为 1 的误报重复。
猜你喜欢
  • 1970-01-01
  • 2011-11-27
  • 2014-10-10
  • 2017-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多