在非常大的数据集中查找重复项 [重复]

Posted

技术标签:

【中文标题】在非常大的数据集中查找重复项 [重复]【英文标题】:Find a duplicate in an extremely large data set [duplicate] 【发布时间】:2017-08-23 17:55:03 【问题描述】:

最近,我在一次采访中被问到以下问题。

Q : 给定一个 N 个整数,其中只有一个是重复的,找出那个重复的数。

我回答了一个解决方案,该解决方案将数字存储在哈希图中,并通过检查是否存在密钥来查找重复项。

他接着说如果数据集非常大,大到不能像连续流一样存储在内存中怎么办?

这有点难倒我。有人可以提出一些答案吗?另外,对于原始问题,除了哈希图之外,还有更有效的解决方案吗?

TIA

【问题讨论】:

" 有人可以提出一些答案吗?另外,对于原始问题,除了哈希图之外,还有更有效的解决方案吗?"不是 *** 的合适问题。这是一个有趣的问题,但它更适合讨论论坛而不是问答网站。见help center。也就是说,您是否想过为每个数字存储一位,并检查该位是否已设置?这样,您可以记录数量等于可用可用内存字节数的 8 倍的数字。 java.util.BitSet 支持 2^31-1 数字,但您可以构建支持更多数字的东西。 地图不太合适 既然我们知道只有一个重复,我相信我们可以在看到重复的那一刻退出程序(尽管流中可能有更多数字),对吧? @KedarMhaswade 当然可以,但关键是你怎么知道这个数字是重复的...... @shole,只是试图澄清要求。这是一个面试问题,所以应该问清楚的问题。 【参考方案1】:

这些整数有多大或多小?如果确定所有整数都在 2^30-1 到 -2^30 或更小的范围内,请尝试 java.util.BitSet。 2^31 位 = 2^28 字节 ~ 2^8 兆字节 = 256 兆字节。这足够小,可以存储在普通笔记本电脑的内存中。

假设整数在2^30-1到-2^30之间,方法简单;对于大数据集中的每个整数i,先设置j = i + 2^30,并检查bitSet.get(j)是否为真,如果为真,重复数为i,否则调用bitSet.set(j, true ) 并继续,直到找到重复项。如果整数在 0 到 2^31 -1 之间,情况类似。

BufferedReader reader = new BufferedReader(
                new InputStreamReader(new FileInputStream("a.txt"), StandardCharsets.UTF_8));
        String line = null;
        BitSet bitSet = new BitSet((1<<31)- 1);
        while ((line = reader.readLine()) != null) 
            int i = Integer.parseInt(line);
            boolean v = bitSet.get(i);
            if (v)
                System.out.println("the duplicate is " + i);
                break;
            else
                bitSet.set(i);
            

        
        reader.close();

如果范围稍微大一点,比如 0 到 2^34 - 1,一个可行的想法是复制粘贴 java.util.BitSet 类并对其进行一些修改以创建一个稍微不同的类;一个 long[] 数组最多可以存储 ((2^31 - 1) * 2^6 - 1) 位。普通计算机仍然可以为一个对象提供 2G 内存。

如果范围较大或者这个查重模块不能占用太多内存,请参考上面cmet中的问题Algorithm for detecting duplicates in a dataset which is too large to be completely loaded into memory

【讨论】:

以上是关于在非常大的数据集中查找重复项 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

您可以将公式应用于数据透视表的计数过滤器吗?尝试在大型数据集中查找重复项

从 SSIS 中加载的数据集中过滤掉重复项

如何找到一个非常大的数组的余弦相似度

django批量创建忽略重复项[重复]

查找 MySQL 数据库中两列组合的重复项

Django 使用查询集和正则表达式查找重复项