海量数据处理面试题
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-255KB,假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。
思路:采用 hash 完成计数,采用小根堆来完成 top k 排序
1) 先对这批海量数据预处理,在 O(n) 的时间内用Hash表完成计数
2) 维护一个大小为 k (这里 k = 10)的小根堆,然后遍历 300万 非重 Query,分别和堆顶元素进行对比,最终的时间复杂度是:$O(n)+O(n’ \log k)$( n 为1000万,n’为300万)
3、有一个 1G 大小的一个文件,里面每一行是一个词,词的大小不超过 16K,内存限制大小是 1M 。返回频数最高的 100 个词。
思路:分治,然后归并
1)将大文件分开,对于每个词 x ,取 hash(x)%5000,然后按照该值存到 5000 个小文件中。这样每个文件大概是200k左右。
2)如果其中的有的文件超过了1M大小,还可以按照类似的方法继续往下分,直到分解得到的小文件的大小都不超过1M。
3)对每个小文件,采用
hash table 统计每个文件中出现的词以及相应的频率,并取出出现频率最大的 100 个词(可以用含100 个结点的最小堆),并把 100
个词及相应的频率存入文件,这样又得到了5000个文件。下一步就是把这5000个文件进行归并(外排)的过程了。
4、有 10 个文件,每个文件 1G ,每个文件的每一行存放的都是用户的 query ,每个文件的 query 都可能重复。要求你按照 query 的频度排序。
1)顺序读取 10 个文件,按照 hash(query)%10 的结果将 query 写入到另外 10
个文件(记为)中。这样新生成的文件每个的大小大约也 1G 。
2)找一台内存在 2G 左右的机器,依次对用 hash_map(query,
query_count) 来统计每个query出现的次数。利用快速/堆/归并排序按照出现次数进行排序。将排序好的query和对应的 query_cout
输出到文件中。这样得到了10个排好序的文件。
3)对这10个文件进行归并排序(内排序与外排序相结合)。
5、 给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
1)遍历文件a,对每个 url 求取 hash(url)%1000 ,然后根据所取得的值将 url 分别存储到 1000 个小文件(记为$a_0, a_1, ..., a_{999}$ )中。这样每个小文件的大约为 300M。
2)遍历文件 b ,采取和 a 相同的方式将 url 分别存储到 1000 小文件(记为 $b_0, b_1, ..., b_{999}$)。这样处理后,所有可能相同的 url 都在对应的小文件($(a_0, b_0),(a_1, b_1),...,(a_{999}, b_{999})$)中,不对应的小文件不可能有相同的 url 。然后我们只要求出 1000 对小文件中相同的 url 即可。
3)求每对小文件中相同的 url 时,可以把其中一个小文件的 url 存储到 hash set 中。然后遍历另一个小文件的每个url,看其是否在刚才构建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。
6、在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
思路:bit map
采用 2-Bitmap(每个数分配 2bit ,00 表示不存在,01 表示出现一次,10 表示多次,11 无意义)进行,共需内存 $2^32 \times 2$ bit=1GB 内存,还可以接受。然后扫描这 2.5 亿个整数,查看 Bitmap 中相对应位,如果是 00 变 01 ,01 变 10 ,10 保持不变。所描完事后,查看 bitmap ,把对应位是 01 的整数输出即可 。
7、腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
思路 : bit map
申请512M的内存,一个bit位代表一个unsigned int值。读入40亿个数,设置相应的bit位,读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在。
8、怎么在海量数据中找出重复次数最多的一个?
先做 hash ,对于数字 n ,hash(n) %
1000 将所有数散列为 1000 个小文件(相同数字都会被映射到一个文件),采用 hashmap 求出每个小文件中重复次数最多的一个,并记录重复次数。然后找出
1000 个中最大的一个即为所求。
9、上千万或上亿数据(有重复),统计其中出现次数最多的前 N 个数据。
上千万或上亿的数据,hash(x) % 1000 为 1000 个小文件,所以考虑采用 hash map 进行次数统计。通过维护一个大小为 N 的小跟堆,取出前 N 个出现次数最多的数据即可。
10、一个文本文件,大约有一万行,每行一个词,要求统计出其中最频繁出现的前10个词,请给出思想,给出时间复杂度分析。
方案1:这题是考虑时间效率。用 trie 树统计每个词出现的次数,时间复杂度是 O(n $\times$ len)(len 表示单词的平均长度)。然后是找出出现最频繁的前 10 个词,可以用小跟堆来实现,前面的题中已经讲到了,时间复杂度是 O(n $\times$ log10)。所以总的时间复杂度,是 Max(O(n $\times$ len), O(n $\times$ log10) )。
11、 求一个论坛的在线人数,假设有一个论坛,其注册ID有两亿个,每个ID从登陆到退出会向一个日志文件中记下登陆时间和退出时间,要求写一个算法统计一天中论坛的用户在线分布,取样粒度为秒。
一天有 N (N = 3600*24=86400)秒,申请两个 N 的数组,一个为 delta ,一个 为 online_num,delta 统计每一秒的上线与下线人数之差,可能为正值或负值,这样统计 第 n 秒 的在线人数的 online_num[n] = online_num[n - 1] + delta [n];