在极大的数据集中查找副本

时间:2017-03-30 01:56:09

标签: java algorithm stream hashmap large-data

最近,我在接受采访时被问到以下问题。

问:给定N个整数,只有一个是重复的,找到重复的数字。

我回答了一个解决方案,该解决方案将数字存储在散列映射中,并通过检查密钥是否存在来查找重复数据。

然后,他跟着如果数据集非常大,那么大,你不能将它存储在内存中,如连续流?

有点难过我。有人可以建议一些答案吗?另外,除了原始问题的哈希映射之外,还有其他更有效的解决方案吗?

TIA

1 个答案:

答案 0 :(得分:2)

这些整数有多大或多小?如果确定所有整数都在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内存。

如果范围较大或此重复查找模块无法占用大量内存,请参阅上面评论中的问题,如Algorithm for detecting duplicates in a dataset which is too large to be completely loaded into memory