数据结构与算法面试题汇编(2)- 海量数据处理

1、从海量日志数据中提取出某日访问百度次数最多的那个IP。

    算法思想:分而治之 + Hash
1)IP地址最多有2^32=4G种取值情况,所以不能完全加载到内存中处理;
2)可以考虑采用“分而治之”的思想,按照IP地址的Hash(IP)%1024值,把海量IP日志分别存储到1024个小文件中。这样,每个小文件最多包含4MB个IP地址;
3)对于每一个小文件,可以构建一个IP为key,出现次数为value的Hash map,同时记录当前出现次数最多的那个IP地址;
4)可以得到1024个小文件中的出现次数最多的IP,再依据常规的排序算法得到总体上出现次数最多的IP;

2、从海量日志记录中提取最频繁字符串:搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。

    问题解析:要统计最热门查询,首先就是要统计每个Query出现的次数,然后根据统计结果,找出Top 10。
    算法思想:Hash表统计 + TOP K算法
1)维护一个key为检索串,value为出现次数的hash table,读一遍日志,每出现一个key,将对应的value加1,使用内存≈300W*256B ≈ 700MB
2)求该hash表中vaue的top 10。维护一个节点为10的小根堆。遍历hash表,与小根堆的根比较,更新堆。

3、有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。

    问题解析:将1G文件全读入内存需要1024M。一次读取时不可能实现的。需要按一定规则把大文件分割成小文件,保证每个小文件中出现的单词不会在其他文件中出现,统计每个小文件中出现次数最多的词,最后合并。
    算法思想:分而治之 + Hash
1)顺序读取文件中每一个词key,按照key的Hash(key)%1024的值,将词写入0,1,2,...,1023号的小文件当中。这样每个小文件最多包含1MB的词
2)对于每个小文件,构造一个为词为key,以出现次数为value的hash table,同时记录当前出现次数最多的那个词
3)建立100个节点的小根堆,遍历这1024个文件中出现最多的词的频率与小根堆的根比较,更新堆。

4、有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序。

    问题解析:首先需要将相同的query写入到一个文件内,然后文件内按query的频度排序,最后输出再输出。 
    算法思想:
    方案一、不考虑内存等限制
1)可依次读入10个文件的每行query,组建以query为key,以出现次数为value的hash table。
2)按照次数对query做快排/堆/归并排序
3)输出每个query出现的次数和query到另一个文件
     方案二、考虑内存限制
1)依次读入文件,按照hash(query)%10,分别将每条query输出到另外的10个文件中
2)分别对每个文件再次读入并按照每个query出现的次数进行快速/堆/归并排序,并输出次数和query到另一个文件中。
3)对这10个内容已排序的文件,进行归并排序,将最终结果输出

5、给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
    问题解析:50亿个url*64B = 320G。内存限制4G,因此要把每个文件至少分成120份儿才可(假设均匀分布),而文件分的越小,处理越快,
    算法思路:分而治之+hash
1)读入a,按hash(url)%1000,将之分别输入到a0,a1,a2,...,a999这1000个文件中
2)读入b,按hash(url)%1000,将之分别输入到b0,b1,b2,...,b999这1000个文件中
3)只需比较<a0,b0>,<a1,b1>,...,<a199,b199>这1000组文件即可。
4)对每组文件,将a文件录入,构造以url为key的hash set;然后读b文件,如果在hash set中存在,这改url在a,b两个文件中均有。
    方案2:如果允许有一定的错误率,可以使用Bloom filter,4G内存大概可以表示340亿bit。将其中一个文件中的url使用Bloom filter映射为这340亿bit,然后挨个读取另外一个文件的url,检查是否与Bloom filter,如果是,那么该url应该是共同的url(注意会有一定的错误率)。

6、在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
    算法思想:
    方案一、采用分而治之的方法。先分割成小文件,在小文件中找不重复的整数。
    方案二、采用2位位图法。此种方法假设这2.5个整数是32位整数,则每两位表示所在索引表示该数,表示所有整数范围一共需要2^32*2=1G内存(如果是64位整数,就不行了)。设申请的内存块为B,依次读入每个整数N,检查B[2N]和B[2N+1]如果是00,这变为01,如果是01这变为10,如果是10,则不变化。最后再遍历一遍该内存块,输出01对应的索引。

7、腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
    方案一、采用1位位图法,申请2^32bit = 512MB的内存B,依次读入N,并置B[N]=1,再给一个数M,如果B[M]的值即可。
    方案二、另类的分而治之。按每位是0或1将之分割成小文件。

8、怎么在海量数据中找出重复次数最多的一个?
    算法思想:分而治之+hash(参考第一题)

9、上千万或上亿数据(有重复),统计其中出现次数最多的前N个数据。
    算法思想:分而治之+hash(参考第二题)

10、一个文本文件,大约有一万行,每行一个词,要求统计出其中最频繁出现的前10个词,请给出思想,给出时间复杂度分析。
    算法思想:读入文件,建立hash_map(word, word_count);建立10个以出现次数和单词为节点的小根堆,读入所有hash_map元素,更新堆。
    算法分析:时间复杂度为O(n*log10)

11、100w个数中找出最大的100个数。
方案1:在前面的题中,我们已经提到了,用一个含100个元素的最小堆完成。复杂度为O(100w*lg100)。
方案2:采用快速排序的思想,每次分割之后只考虑比轴大的一部分,知道比轴大的一部分在比100多的时候,采用传统排序算法排序,取前100个。复杂度为O(100w*100)。
方案3:采用局部淘汰法。选取前100个元素,并排序,记为序列L。然后一次扫描剩余的元素x,与排好序的100个元素中最小的元素比,如果比这个最小的要大,那么把这个最小的元素删除,并把x利用插入排序的思想,插入到序列L中。依次循环,知道扫描了所有的元素。复杂度为O(100w*100)。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章