我听说这个面试问题问了很多,我希望就好的答案给出一些意见:您有一个大于10 GB的大文件,并且您想找出哪个元素出现得最多,什么是好的方法去做这个?
在地图上进行迭代并保持跟踪可能不是一个好主意,因为您会占用大量内存,并且在条目进入时保持跟踪并不是最好的选择,因为提出此问题时文件通常已经存在。
我想到的其他想法包括拆分要迭代的文件并由多个线程处理,然后将这些结果组合在一起,但是映射的内存问题仍然存在。
我听说这个面试问题问了很多,我希望就好的答案给出一些意见:您有一个大于10 GB的大文件,并且您想找出哪个元素出现得最多,什么是好的方法去做这个?
在地图上进行迭代并保持跟踪可能不是一个好主意,因为您会占用大量内存,并且在条目进入时保持跟踪并不是最好的选择,因为提出此问题时文件通常已经存在。
我想到的其他想法包括拆分要迭代的文件并由多个线程处理,然后将这些结果组合在一起,但是映射的内存问题仍然存在。
Answers:
当您有一个非常大的文件且其中包含许多元素时,但最常见的元素非常常见-出现时间小部分-您可以在线性时间中以单词(表示法中的常数非常小,如果不计入哈希等辅助性事物的存储量,则基本上为2。此外,这对于外部存储非常有用,因为文件一次按顺序处理一个元素,并且算法永不“回头”。一种实现方法是通过Misra和Gries的经典算法,请参阅这些讲义。现在,该问题被称为“重击手”问题(频繁的元素是重击手)。O (k )O ()
假设最频繁的元素出现的时间>一小部分的几分之一似乎很强,但这在一定程度上是必要的!即,如果您可以顺序访问文件(并且如果文件很大,则随机访问会太昂贵),则任何算法总是在恒定的遍数中找到最频繁的元素,那么该算法将在元素数量中使用线性空间。因此,如果您不对输入进行任何假设,就无法击败哈希表。最频繁的元素非常频繁的假设可能是解决负面结果的最自然的方法。k
这是的草图,即当单个元素出现的时间超过一半时。这种特殊情况被称为多数投票算法,这是由于Boyer和Moore所致。我们将保留一个元素和一个计数。将计数初始化为1并存储文件的第一个元素。然后依次处理文件:
稍加思考,便会说服您,如果存在“多数”元素,即,出现时间超过一半的元素,那么在处理完整个文件后,该元素将成为存储的元素。
对于一般,保留元素和计数,然后将元素初始化为文件的前不同元素,并将计数初始化为每个元素在看到第个元素之前出现的次数。独特的元素。然后,您执行基本上相同的过程:每次遇到元素时,其元素的计数都会增加;如果遇到未存储的元素,则所有元素的计数都会减少;当某个元素的计数为零时,该元素将被踢出,从而有利于文件的当前元素。这是Misra-Gries算法。k - 1 k - 1 k k
当然,您可以使用哈希表来索引存储的元素。在终止时,保证该算法返回出现时间超过分数的任何元素。从本质上讲,这是对算法进行的最佳选择,该算法使文件中的传递次数恒定并且仅存储字。1 / k O (k )
最后一件事:找到候选“沉重击球手”(即频繁元素)后,您可以再遍历文件以计算每个元素的频率。这样,您可以将元素彼此排名,并验证所有元素是否均以超过时间的比例出现(如果少于这样的元素,则算法返回的某些元素可能为假阳性)。1 / k k − 1