在面试中我们会经常遇到和海量数据处理相关的问题,在这里我们将问题进行一个汇总,保证将来我们在遇到海量数据相关问题的时候能够快速解答。
改文章参考:https://blog.csdn.net/v_JULY_v/article/details/6279498
一.100亿个32位的整数,如何最快找到中位数,并要求时间复杂度为O(N)?
如果内存能够全部装下:直接使用快速排序。
如果内存不能够全部装下:先将第一个字节,也就是前8位进行分桶,可以分为256个桶,也就是将100亿的整数分别按照第一个字节的大小装入这256个桶(桶是外置文件)之中;如果内存仍然不能够全部装下中位数所在桶中的全部数据,那再将该桶按照第二个字节的大小进行划分,也就是在已经分了256个桶的基础上再分256个桶。按照这种逻辑,直到内存能够将中位数所在的桶全部装下,然后进行快速排序即可。
二.海量日志数据,如何提取出某日访问百度次数最多的IP?
IP地址是有限的,也就是 232 个,所以可以将所有的ip地址都存入哈希表之中,再将海量的日志数据读取进入内存统计IP地址出现的频率即可,统计完之后即可找出访问次数最多的IP。
如果不能将所有IP地址存入内存,那么按照前8位(也就是第一个字节)划分成256个桶(如果内存仍然不能够装下那么就将第二个字节也划分桶),分别找出每个桶最高频IP,然后再在256个IP中挑选最高频的IP 。
三.搜索引擎将每次用户检索的检索串记录下来,每个检索串的长度为1~255字节,假设现在有一千万个检索串,请统计出最热门的10个检索串,要求使用的内存不超过1G。
首先对所有的检索串进行一个预处理,也就是统计不同串的词频;然后再使用TopK算法,建立一个小根堆,该堆的大小为10,依次将整个检索串词频读入内存,完成依次遍历之后也就能找到频率最高的10个检索串。时间复杂度为O(NlogK),空间复杂度为O(K),K为10。
四.有一个1G大小的一个文件,里面的每一行是一个词,词的大小不超过16字节,内存限制大小为1M。返回频数最高的100个词。
创建存储100个词的最小堆,然后依次读取1G大小的文件即可。
五.有10个文件,每个文件1G,每个文件的每一行存放的是用户的query,每个文件的query可能会重复,将所有文件的query按照频率进行排序。
在内存中创建哈希表统计所有query的词频,然后根据词频使用快速/归并/堆排序即可。
六.给a,b两个文件,各自存放50亿个URL,每个URL占用64个字节,内存限制为4G,找出a,b文件共同的URL。
4G的内存不可能将文件a或者文件b中所有的URL全部装下,那么我们将文件a拆分成100份,每一份都设置一个哈希表,然后依次遍历文件b,将共同的(或者说是哈希表中重复的)URL写到新文件中即可找到a,b文件中共同的URL。
七.在2.5亿个整数中找出不重复的整数(内存不能同时存储这2.5亿个整数)?
将2.5亿个整数分成多个文件(保证内存能够将每一个小文件全部装入内存),划分方式按照前8位划分,按照第一个字节(前8位划分)可以分成256个不同的文件,可以将每一个小文件全部装入内存,之后就能够找出不重复的数。如果按照第一个字节(前8位划分)仍然不能全部装入内存,那么就按照第二…三…个字节划分。
八.给40亿个不重复的unsigned int 整数,没有排过序的,再给一个数,如何判断这个数是否在那40亿个数中?
对这40亿个数通过字节进行分桶(与上一题方法类似),然后找到目标数对应的文件桶,将整个文件装入内存后进行排序,然后通过二分查找即可判断该数是否存在于40亿个数中。
在《编程珠玑》中的方法为:通过第一位为1或者0进行折半,分为两个文件;在将第二位,第三位为1或者0进行折半,这样通过不断的折半到最后就可以找到目标数是否在40亿个数中。时间复杂度为O(logN)。
九.如何在海量数据中找到重复次数最多的一个?
将海量数据划分为多个小文件,找出每一个小文件中重复次数最多的那一个,最后汇总即可找到海量数据中重复次数最多的那一个。