1.给出一个超过100G的log file, log中存着ip地址,设计算法找到出现次数最多的ip地址?
思路:
由于文件超过100G,所以我们只能对文件切分,然后再利用数据结构来求解。难点就是如何切分效率最高???
解决方法
这个时候我们可以使用哈希切分,将同一个ip都分割在同一个文件,注意同一个ip经过同一个散列哈希函数一定会进入同一个文件中,然后再统计每一个文件中出现最多的ip的次数,最后将这些进行顺序比较就能的到结果。
又出现一个新的问题?
最极端的情况:如果经过哈希散列函数之后一个ip次数特别多,多到存放这个ip的文件存储不了,怎么办?
这种情况虽然概率很低,但也有可能,博主具体的做法是将这个文件在切分(普通的切分)成若干个小文件,将每一个小文件加载到内存中使用hashTable求出ip出现的次数,最后再将这些小文件的结果汇总后在求出出现次数最多的ip。
2.在上一题的基础上,如何快速找到Top K的ip?
解决方法:
在上一题的基础上,可以借助堆,如果想求每个文件出现次数最多的前K个ip,我们可以使用最小堆,逐个进堆,向下调整,最后堆的元素就是所需元素。如果是次数最小的前K个ip,同理,键一个大堆。
3.给定100亿个整数,设计算法快速找到只出现一次的整数?
ps:100亿 * sizeof(int) ≈ 40G
方法一:切分 + 哈希
首先,我们可以把这100亿个整数分成100份,平均每一份400M左右,再把每一份加载到内存中,使用哈希表进行查找只出现一次的数,最后把这一百份的查找结果汇总到一起在进行查找。
方法二:bitmap(位图)
这个题不能直接用位图,因为这些数有可能出现0次,1次,两次。。。。,只用一个bit位无法表示,所以我们要改变一下思路,不在用比特位来表示每一个数的次数,题目只要求一次,我们可以把情况化为三种情况:出现0次的数字,出现1次的数字,和出现 > 1次的数字。具体做法就是用两个bit位表示,00表示出现0次的数字,01表示出现一次的数字,10(11)表示出现 > 1次的数字。
整型能表示42亿9千万多个数,至少要16G才能存下这些数字,如果换成两个bit位表示的话只需要1G的内存就足够了。因为这些整数有可能有负数,所以我们可以将负数映射到位图的后半部分,也就是将这些负数当做无符号的数看待。
方法三:
整数有32位,我们依次从第一位到第三十二位来划分,每一位分成 0 和 1 两种情况,相同的分成一组,一直划分到第三十二位,这样最多只需要三十二次划分就能判断出出现一次数字。
4.给定两个文件,分别有100亿个整数,只提供1G内存,如何找出两文件交集?
方法一:切分 + 暴力
把一个文件切分成100多份,分别把每一份加载到内存中,然后用第二个文件中的数据到每一份中都进行查找。这种方法的时间复杂度是O(N^2)。
方法二:切分 + 哈希
先对一个文件进行切分,不过这次切分的时候使用一个散列函数,将相同的数都分割到一个文件中去,注意相同的数一定会进入同一个文件,并给这些文件进行编号。再对第二个文件中的数据也使用这个散列函数,并给切分后的文件也进行编号。最后,编号相同的文件即是两个文件的交集,这种方法的时间复杂度是O(N).
方法三:bitmap(位图)
将一个文件中的数据映射到位图中(大约需要500M),然后再用第二个文件数据映射,如果该位图位置为一,则为交集这种方法的时间复杂度是O(N)。但存在误差(因为布隆过滤器的一个位,可能表示多个key)
5.给定两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件的交集?分别给出精确算法和近似算法?
精确算法:哈希切分
如果要得到精确的结果的话,我们可以使用哈希切分,第四题的方法2是一样的,不过在这个题中要将query转换成一个整形,然后再经过散列函数映射到文件中去。
近似算法:bloomfilter(布隆过滤器)
如果要得到近似结果的话可以使用布隆过滤器,和第四题方法三一样。因为布隆过滤器的一个位,可能表示多个key。