1.top K问题
分治/hash映射+hashmap统计+堆排序
(PS: 1.如果数据可以一次性放入内存则不需要分治;2.topK小用大根堆,topK大用小根堆;)
分治/hash映射:数据太大,内存受限;把大文件化成(取模映射)M个小文件;
hash统计:使用hashmap来进行频率统计;得到M个文件的map;
堆排序:维护K的堆,依次遍历M个文件;得到最后的topK;
参考:topK问题
参考:海量数据问题
2.海量数据找一个数是否存在(存在、重复、不重复)
Bit-map
腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
unsigned int 最多有2^32个数,用位图的方法,申请512M(512*2^20*8=2^32)的内存,一个bit位代表一个unsigned int值。读入40亿个数,设置相应的bit位,读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在;
(1MB=1024KB,1KB等于1024B,1B=8bit,1KB=1024*8bit;一个int占4个字节即4*8个bit)
(位图法,每个int数对应一个bit位;共需要2^32/8=2^29B=2^9MB=512M)
3.
例题:
1.海量日志数据,找出某天访问百度次数最多的ip
最多次数问题:hash映射+hashmap频率统计;
IP-32位,最多2^32个;模1000分成1000个文件夹,对每个文件夹hashmap统计频率,并保留最大的;最后在1000个最大的ip中,找出最大的;
2.寻找热门查询,300万个查询字符串中统计最热门的10个查询
topK问题:分治/hash映射+hash统计+堆排序;
每个查询串长度<255字节Byte,300万个=3*10^6*2^8B=3*2^8MB=0.75G(只计算非重复占的内存);小于题目要求1G;所以不用分治;hash统计,维护hashmap(query,value);复杂度为O(1000W);第二步:最小堆,找出前10个,时间复杂度为300W*O(log10);总的时间复杂度为两个相加;
3.有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
topK问题:分治+hash统计+堆排序;
1G>1M;所以
- 分治,取hash(x)%5000,分成5000个文件;每个文件200k左右;
- hash统计;
- 堆排序:利用堆排序,依次遍历5000个文件,得到最后的top100;
(疑问:如果词被分在不同文件,在单独的文件里没有进top100,但是其实加起来是可以进的呢?)
答:Hash取模是一种等价映射,不会存在同一个元素分散到不同小文件中的情况,即这里采用的是mod1000算法,那么相同的IP在hash取模后,只可能落在同一个文件中,不可能被分散的。因为如果两个IP相等,那么经过Hash(IP)之后的哈希值是相同的,将此哈希值取模(如模1000),必定仍然相等。参考:海量数据
4.给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
找两个文件相同部分:分治+set;
将a/b用hash映射的方式放到1000个小文件;比较每个小文件:hashset放入a的数据再遍历b的;
5.在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
找不重复的数:bit-map
采用2-Bitmap(每个数对应2bit,00不存在,01一次,10多次)
内存是2^32 * 2bit = 1G;远小于2.5*10^8*32了;
扫描2.5亿个整数;00变01,01变10,10不变;最后输出01的;
6.腾讯面试题:给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
找数是否存在:bit-map
unsigned int 最多有2^32个数,用位图的方法,申请512M(512*2^20*8=2^32)的内存,一个bit位代表一个unsigned int值。读入40亿个数,设置相应的bit位,读入要查询的数,查看相应bit位是否为1,为1表示存在,为0表示不存在;