处理海量数据的常规思路
分而治之/Hash映射 + Hash_map统计 + 堆/快速/归并排序
1、海量日志数据,提取出某日访问百度次数最多的那个IP
1.)分而治之/hash映射:把大文件化成(取模映射)小文件
2)hash_map统计:当大文件转化了小文件,那么我们便可以采用常规的hash_map(ip,value)来进行频率统计O(n)复杂度
3)堆/快速排序:得到每个文件次数最多的IP,然后汇总这几个文件排序取最大的ip次数
首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中。注意到IP是32位的,最多有个2^32个IP。同样可以采用hash映射的方法,比如%1000,把整个大文件映射为1000个小文件,再找出每个小文件中出现频率最大的IP(可以采用hash_map对那1000个文件中的所有IP进行频率统计,然后依次找出各个文件中频率最大的那个IP)及相应的频率。然后再在这1000个最大的IP中,找出那个频率最大的IP,即为所求。
2、寻找热门查询,300万个查询字符串中统计最热门的10个查询
- 重复度高内存可以容纳:
直接hashmap统计+堆排序 Top K - 重复度低内存不够:
hash映射到多个文件->每个文件hashMap统计->文件内堆排序取Top K->
汇总每个文件的topK,使用堆排再取topK
注意:针对TOPK的场景,可以使用最小堆(klogk+(n-k)logk)=O(n*logk).
维护k个元素的最小堆,遍历出k个数存储到堆.然后继续遍历,与堆顶比较,如果大于堆顶,则入到堆中 如果比堆顶元素小,则不更新堆
最终时间复杂度O(N) + N' * O(logK),(N为1000万,N’为300万)。
3、有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词
1.hash映射:顺序读文件中,对于每个词x,取hash(x)%5000,然后按照该值存到5000个小文件(记为x0,x1,...x4999)中
这样每个文件大概是200k左右。如果其中的有的文件超过了1M大小,还可以按照类似的方法继续往下分,直到分解得到的小文件的大小都不超过1M
2.hash_map统计:对每个小文件,采用trie树/hash_map等统计每个文件中出现的词以及相应的频率
3.堆/归并排序:取出出现频率最大的100个词(可以用含100个结点的最小堆)后,再把100个词及相应的频率存入文件,这样又得到了5000个文件。最后就是把这5000个文件进行归并(类似于归并排序)的过程了
- 海量数据分布在100台电脑中,想个办法高效统计出这批数据的TOP10
两种情况:
-
同一元素分布在同一台机器
‘堆排序:在每台电脑上求出TOP10,可以采用包含10个元素的堆完成
求出每台电脑上的TOP10后,然后把这100台电脑上的TOP10组合起来,共1000个数据(归并) -
但如果同一个元素重复出现在不同的电脑中呢
有两种方法:
1.遍历一遍所有数据,重新hash取摸,如此使得同一个元素只出现在单独的一台电脑中,然后采用上面所说的方法,统计每台电脑中各个元素的出现次数找出TOP10,继而组合100台电脑上的TOP10,找出最终的TOP10。
2.暴力求解:直接统计统计每台电脑中各个元素的出现次数,然后把同一个元素在不同机器中的出现次数相加,最终从所有数据中找出TOP10。
5、有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序
hash映射/取模->hashMap统计->单文件堆排序->多文件归并
6、 给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
1.分而治之/hash映射:遍历文件a,对每个url求取,然后根据所取得的值将url分别存储到1000个小文件。这样每个小文件的大约为300M。遍历文件b,采取和a相同的方式将url分别存储到1000小文件中(记为)。这样处理后,所有可能相同的url都在对应的小文件(
)中,不对应的小文件不可能有相同的url。然后我们只要求出1000对小文件中相同的url即可。
2.hash_set统计:求每对小文件中相同的url时,可以把其中一个小文件的url存储到hash_set中。然后遍历另一个小文件的每个url,看其是否在刚才构建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。
7、怎么在海量数据中找出重复次数最多的一个?
hash映射/取模->hashMap统计->单文件堆排序->多文件归并
8、上千万或上亿数据(有重复),统计其中出现次数最多的前N个数据。
hash映射/取模->hashMap统计->单文件堆排序->多文件归并
9、一个文本文件,大约有一万行,每行一个词,要求统计出其中最频繁出现的前10个词,请给出思想,给出时间复杂度分析。
O(N) + N' * O(logK),(N为1万,N’为hashmap的key的元素 算1万吧,K=10)
-
1000万字符串,其中有些是重复的,需要把重复的全部去掉,保留没有重复的字符串。请怎么设计和实现?
hash_map -
一个文本文件,找出前10个经常出现的词,但这次文件比较长,说是上亿行或十亿行,总之无法一次读入内存,问最优解。
hash映射/取模->hashMap统计->单文件堆排序->多文件归并 -
100w个数中找出最大的100个数。
用一个含100个元素的最小堆完成。复杂度为O(100w*lg100)
13、2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。
https://www.jianshu.com/writer#/notebooks/45731388/notes/70253940/preview
- 5亿个int找它们的中位数
分治法的思想是把一个大的问题逐渐转换为规模较小的问题来求解。
对于这道题,顺序读取这 5 亿个数字,对于读取到的数字 num,如果它对应的二进制中最高位为 1,则把这个数字写到 f1 中,否则写入 f0 中。通过这一步,可以把这 5 亿个数划分为两部分,而且 f1 中的数都大于 f0中的数。
划分之后,可以非常容易地知道中位数是在 f0 还是 f1 中。假设 f0中有 1 亿个数,那么中位数一定在 f1 中,且是在 f1 中,从小到大排列的第 1.5 亿个数与它后面的一个数的平均值。
对于 f1可以用次高位的二进制继续将文件一分为二,如此划分下去,直到划分后的文件可以被加载到内存中,把数据加载到内存中以后直接排序或使用快排或堆排序(小顶堆) 找出第K大的数,从而找出中位数。
https://mp.weixin.qq.com/s/rdz4pfTCeX1ahOM4KAi3oQ
https://blog.csdn.net/randyjiawenjie/article/details/6968591
https://blog.csdn.net/v_july_v/article/details/7382693
https://mp.weixin.qq.com/s/VXGtJ9Miwfc1yD3v44kvnw
网友评论