这是一个采访问题:
有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 十亿个数字?使用尽可能少的内存。
我想出了两个解决方案,
如上所述,电话号码可以使用5B表示,扫描文件,一次读取一个数字,is or is not in
,如果结果是xor the given number with the one read from the file
,则给定一个在文件中,它需要0
时间,对吗?
O(n)
根据Partition
将这些数字加入2 small files
,这意味着带有leading bit
的数字会转到文件leading 1-bit
转到另一个文件,同时计算每个文件中的数字,如果给定的数字落入1位文件并且1位文件的leading 0-bit
是count
,那么not full
根据{{1}}的1位文件,递归检查给定的数字;如果1位文件again partition
,那么给定的数字必须在文件中,它将花费secondary leading-bit
时间,对吗?
答案 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哈希函数。 虽然我不确定你可能需要多少哈希函数。