【发布时间】:2016-02-19 18:01:32
【问题描述】:
我最近参加了一次采访。我被问到以下问题:
您有具有不同值的文本文件,每行一个。如何找到存在于最大行数/条目数中的一个值?
我给出了 hashmap 作为具有恒定时间复杂度的解决方案。
然后面试官换了个问题,问如果文件有100亿行怎么办?
现在我不能使用哈希图。我想不出办法。 任何人都可以提出一种方法。
有没有办法将相同的项目组合在一起?
【问题讨论】:
我最近参加了一次采访。我被问到以下问题:
您有具有不同值的文本文件,每行一个。如何找到存在于最大行数/条目数中的一个值?
我给出了 hashmap 作为具有恒定时间复杂度的解决方案。
然后面试官换了个问题,问如果文件有100亿行怎么办?
现在我不能使用哈希图。我想不出办法。 任何人都可以提出一种方法。
有没有办法将相同的项目组合在一起?
【问题讨论】:
您可以对文件进行排序,然后执行一次只需要 O(1) 内存的过程。
【讨论】:
O(1)内存的文件进行排序?
如果值的范围限制为 32 位整数,一种简单的方法是保留一个 4GiB 的 8 位饱和计数器数组。
您可以在运行中转换为使用更长的计数器,以使其成为一次性算法。 255 是计数器的标记值,这意味着您应该改为引用值的哈希图 -> 64 位计数器。
如果 4GiB 太多,您可以使用 4 位饱和计数器,但是更多的计数器会饱和,它们的更新速度会更慢(尽管内存仍然是瓶颈,无论是否有额外的移位指令/mask/recombine-with-old-value)。
使用多级方法没有意义(1 位饱和计数器,然后是 8 位饱和计数器,...),因为第一个之后的所有级别都必须是稀疏的(或者没有意义)。稀疏映射的每个条目开销,如哈希或树,将主导实际计数器的大小,因此为密集的第一级使用尽可能多的内存,然后回退到哈希映射二级64位计数器。
在计算重复项时分批排序,然后合并这些批次。例如,请参阅我对Memory-constrained external sorting of strings, with duplicates combined&counted, on a critical server (billions of filenames) 的回答,以获取有关如何在批处理时最大化效率的建议。那是针对字符串,而不是整数,但是像Tries 这样的方法可以在运行中以良好的空间效率计算重复项,对于数字字符串比对任意字符串更有效。 Radix Trie(节点可以表示字符串,而不仅仅是字符)可能比这么小的字母表更麻烦。
在任何情况下,如果要进行排序,请计算重复次数,直到您在编写批处理之前使用了尽可能多的可用内存。您在第一遍中找到并计数的每个重复项都是以后不必合并的。
【讨论】:
将所有值按照hashvalue分成若干个文件,然后对每个文件使用hashmap。
而且,时间复杂度是O(n)而不是O(1)
【讨论】:
1, 2, 3, 4, 5, 1, 4, 1一样,号码应该是1,因为有1。