检查10亿个手机号码是否有重复

时间:2011-10-09 11:02:05

标签: algorithm large-data

这是一个采访问题:

  

有10亿个手机号码有11个数字,它们随机存储在一个文件中   例如12345678910,第一个数字必须是1.通过这些数字来查看是否存在   一个有重复,只要看看是否存在重复,如果找到重复,   返回True,或返回False。   仅允许10 MB内存。

这是我的解决方案:

使用hash(num)%1000将所有这些数字哈希到1000个文件中,然后重复项应归入同一个文件。

散列后,我收到了1000个小文件,每个文件都包含1 million个数字at most,对吧?我不确定这一点,我只是做1 billion / 1000 = 1 million

然后,对于每个文件,构建一个哈希表来存储每个数字,并flag表示它的出现。

我想,代表5 B的数字4 B代表上8 digits的{​​{1}}和上1 B的{​​{1}};实际上3 digits就足以满足1 bit,因为我只需要知道重复是否存在,只有多少次。但是如何将flag标志应用于每个数字?我被绊倒了,所以我选择1 bit作为标志,bool被采用。 最后,哈希表中的每个数字都将取1 B,然后每个文件将以5B<for number> + 1B<for flag> + 4B<for the next-pointer> = 10B为哈希表。

这是我的愚蠢解决方案,请给我一个更好的解决方案。

感谢。

关注:

  

如果这10亿个电话号码中有10M,则给定一个   电话号码,如何查找给定的no duplicates这些1   十亿个数字?使用尽可能少的内存

我想出了两个解决方案,

  1. 如上所述,电话号码可以使用5B表示,扫描文件,一次读取一个数字,is or is not in,如果结果是xor the given number with the one read from the file,则给定一个在文件中,它需要0时间,对吗?

  2. O(n)根据Partition将这些数字加入2 small files,这意味着带有leading bit的数字会转到文件leading 1-bit转到另一个文件,同时计算每个文件中的数字,如果给定的数字落入1位文件并且1位文件的leading 0-bitcount,那么not full根据{{​​1}}的1位文件,递归检查给定的数字;如果1位文件again partition,那么给定的数字必须在文件中,它将花费secondary leading-bit时间,对吗?

6 个答案:

答案 0 :(得分:14)

最快的解决方案(也就程序员开销而言:)

# Generate some 'phones'
yes 1 | perl -wne 'chomp; ++$a; print $_."$a\n";' > phones.txt

# Split phones.txt in 10MB chunks
split -C 10000000 phones.txt

# Sort each 10MB chunk with 10MB of memory
for i in x??; do sort -S 10M $i > $i.srt; echo -ne "$i.srt\0" >> merge.txt; done

# Merge the shorted chunks with 10MB of memory
sort -S 10M --files0-from=merge.txt -m > sorted.txt

# See if there is any duplicates
test -z $(uniq -d merge.txt)

检查pmap $(pidof sort)是否符合内存使用限制,例如:

答案 1 :(得分:8)

  

散列后,我得到了1000个小文件,每个文件包含1个   对,

最多数百万

不正确,在极端情况下,一个文件可能包含所有数字。

根据数字的第一个或最后一个x位创建文件(忽略起始1)。创建这些文件时,您实际上可以将这些数字切掉,因为它们在文件中是相同的。这比哈希要好得多,因为尽管所有数字仍然可以在一个文件中结束,但现在这些数字的范围是有限的,所以你可以将它装入10MB。

每个数字都可以通过一个简单的位来表示,因为您需要的唯一信息是先前是否出现过这个数字。您不必存储实际数字,该位的地址是数字。在10MB中你可以存储80M位,所以你需要1G / 80M = 12.5个文件,但请记住,这些数字必须不同,所以实际上你需要100个文件(x = 2)。

最后,您不必创建这些文件,也可以多次扫描整个文件。在这种情况下,你可以在内存中有多个位图,因为一个不占用10MB。

我强烈建议您阅读本书,它以一个几乎相同的示例开头:http://www.amazon.co.uk/Programming-Pearls-ACM-Press-Bentley/dp/0201657880

答案 2 :(得分:5)

不需要散列,10M = 83886080位,将每个数字放入[0,83886080],[83886080,83886080 * 2] ...... [xx,9999999999)(不考虑第一位数),约999999999 / 83886080 = 120个文件,然后构建bit set,它完全占用O(n)。

答案 3 :(得分:2)

您可以遵循bitset技术。请参阅此问题和答案:Find an integer not among four billion given ones

答案 4 :(得分:0)

面试问题仅限制使用的记忆,而不是提供答案所需的时间。

因此可以合理地实施这样的问题:

take the first number
compare it to all numbers following it
take the second number
compare it to all numbers following it
...

这需要花费大量时间来处理十亿个数字(O(n ^ 2)),但不会占用超过10MB的内存空间。

答案 5 :(得分:0)

您可以使用包含m位数组的Bloom过滤器并使用k哈希函数。 虽然我不确定你可能需要多少哈希函数。