文章目录
Top K 问题
在大规模数据处理中,经常会遇到的一类问题:在海量数据中找出出现频率最好的前k个数,或者从海量数据中找出最大的前k个数,这类问题通常被称为top K问题
如何在100亿数据中找到最大的1000个数
最容易想到的就是将数据全排序,但是效率太低了,对于海量数据处理并不合适。
一、构建堆
用构建堆。(找1000个最大的数,构建最小堆)找1000个最小的数构建最大堆
我们知道完全二叉树有几个非常重要的特性,就是假如该二叉树中总共有N个节点,那么该二叉树的深度就是log2N,
对于小顶堆来说移动根元素到 底部或者移动底部元素到根部只需要log2N,相比N来说时间复杂度优化太多了(1亿的logN值是26-27的一个浮点数)
具体思路:先从文件中取出1000个元素构建一个最小堆数组(O(log 1000)),然后对剩下的100亿-1000个数字m进行遍历,如果当前元素大于 最小堆的堆顶,
就是K【0】元素,就用m取代k【0】,对新的数组从新构建小根堆。遍历结束,这个最小堆就是要找的数。
时间复杂度:O((100亿 - 1000)log 1000) 就是O((N-M)logM), 空间复杂度M
这个算法优点是性能尚可,空间复杂度低,IO读取比较频繁,对系统压力大。
二、分治法 即大数据里最常用的MapReduce。a、将100亿个数据分为1000个大分区,每个区1000万个数据
二级分区
b、每个大分区再细分成100个小分区。总共就有1000*100=10万个分区
c、计算每个小分区上最大的1000个数
d、合并每个大分区细分出来的小分区。每个大分区有100个小分区,我们已经找出了每个小分区的前1000个数。将这100个分区的1000*100个数合并,找出每个大分区的前1000个数。
e、合并大分区。我们有1000个大分区,上一步已找出每个大分区的前1000个数。我们将这1000*1000个数合并,找出前1000.这1000个数就是所有数据中最大的1000个数
(a、b、c为map阶段,d、e为reduce阶段)
三、Hash法。
如果这1亿个书里面有很多重复的数,先通过Hash法,把这1亿个数字去重复,这样如果重复率很高的话,会减少很大的内存用量,从而缩小运算空间,
然后通过分治法或最小堆法查找最大的10000个数。