我最近参加了一次采访。我被问到以下问题:
每行有一个不同值的文本文件。如何找到最大行数/条目中存在的一个值?
我将hashmap作为具有恒定时间复杂度的解决方案。
然后面试官改变了问题并询问如果文件有100亿行怎么办?
现在我不能使用hashmap。我无法想到一种方法。 任何人都可以建议一种方式。
有没有办法将相同的项目组合在一起?
答案 0 :(得分:4)
您可以对文件进行排序,然后执行一次只需要O(1)内存的传递。
答案 1 :(得分:1)
如果值的范围限制为32位整数,一种简单的方法是保持4Gbit阵列的8位饱和计数器。
你可以转换为使用更长的计数器来保持它的一次通过算法。 255是计数器的标记值,这意味着您应该改为引用值的散列图 - > 64位计数器。
如果4GiB过多,你可以使用4位饱和计数器,但是你的计数器会更多饱和,并且它们的更新速度会慢一些(尽管内存仍然是瓶颈,无论转移的额外指令如何/掩模/重组与 - 旧值)。
使用多级方法(1位饱和计数器,然后是8位饱和计数器......)是没有意义的,因为第一级之后的所有级别都必须是稀疏的(或者没有点)。稀疏映射的每个条目开销(如散列或树)将占据实际计数器的大小,因此尽可能多地使用密集的第一级内存,然后回退到哈希映射的哈希映射第二级64位计数器。
在计算重复项时批量排序,然后合并这些批次。例如,请参阅我对Memory-constrained external sorting of strings, with duplicates combined&counted, on a critical server (billions of filenames)的回答,了解如何在批量处理时最大限度地提高效率。这是针对字符串而不是整数,但像Tries这样的方法可以在空间效率良好的情况下动态计算重复数据,对于数字字符串而言比使用任意字符串更好。 Radix Trie(节点可以表示字符串,而不仅仅是字符)可能比这么小的字母表更麻烦。
在任何情况下,如果排序,请计算重复项,直到您在编写批处理之前使用了尽可能多的内存。您在第一次传递中找到并计算的每个副本都是以后不必合并的副本。
答案 2 :(得分:0)
根据哈希值将所有值划分为多个文件,然后对每个文件使用hashmap。
,时间复杂度为O(n)
而非O(1)