heavy-hitters
寻找数据流中出现最频繁的
这题也是从实践中提炼而来的,例如搜索引擎的热搜榜,找出访问网站次数最多的前
方案1: HashMap + Heap
用一个 HashMap<String, Long>
,存放所有元素出现的次数,用一个小根堆,容量为
- 每次从数据流来一个元素,如果在
HashMap 里已存在,则把对应的计数器增1 ,如果不存在,则插入,计数器初始化为1 - 在堆里查找该元素,如果找到,把堆里的计数器也增
1 ,并调整堆;如果没有找到,把这个元素的次数跟堆顶元素比较,如果大于堆丁元素的出现次数,则把堆丁元素替换为该元素,并调整堆
- 空间复杂度
O(n)
。HashMap 需要存放下所有元素,需要O(n)
的空间,堆需要存放k 个元素,需要O(k)
的空间,跟O(n)
相比可以忽略不急,总的时间复杂度是O(n)
- 时间复杂度
O(n)
。每次来一个新元素,需要在HashMap 里查找一下,需要O(1)
的时间;然后要在堆里查找一下,O(k)
的时间,有可能需要调堆,又需要O(logk)
的时间,总的时间复杂度是O(n(k+logk))
,k 是常量,所以可以看做是O(n) 。
如果元素数量巨大,单机内存存不下,怎么办? 有两个办法,见方案
方案2: 多机HashMap + Heap
- 可以把数据进行分片。假设有
8 台机器,第1 台机器只处理hash(elem)%8==0
的元素,第2 台机器只处理hash(elem)%8==1
的元素,以此类推。 - 每台机器都有一个
HashMap 和一个Heap, 各自独立计算出top k 的元素 - 把每台机器的
Heap ,通过网络汇总到一台机器上,将多个Heap 合并成一个Heap ,就可以计算出总的top k 个元素了
方案3: Count-Min Sketch + Heap
既然方案
- 在数据流不断流入的过程中,维护一个标准的
Count-Min Sketch 二维数组 - 维护一个小根堆,容量为
k - 每次来一个新元素,
- 将相应的
sketch 增1 - 在堆中查找该元素,如果找到,把堆里的计数器也增
1 ,并调整堆;如果没有找到,把这个元素的sketch 作为钙元素的频率的近似值,跟堆顶元素比较,如果大于堆丁元素的频率,则把堆丁元素替换为该元素,并调整堆
- 将相应的
这个方法的时间复杂度和空间复杂度如下:
- 空间复杂度
O(dm)
。m 是二维数组的列数,d 是二维数组的行数,堆需要O(k)
的空间,不过k 通常很小,堆的空间可以忽略不计 - 时间复杂度
O(nlogk)
。每次来一个新元素,需要在二维数组里查找一下,需要O(1)
的时间;然后要在堆里查找一下,O(logk)
的时间,有可能需要调堆,又需要O(logk)
的时间,总的时间复杂度是O(nlogk)
。
方案4: Lossy Counting
- 建立一个
HashMap<String, Long> ,用于存放每个元素的出现次数 - 建立一个窗口(窗口的大小由错误率决定,后面具体讨论)
- 等待数据流不断流进这个窗口,直到窗口满了,开始统计每个元素出现的频率,统计结束后,每个元素的频率减
1 ,然后将出现次数为0 的元素从HashMap 中删除 - 返回第
2 步,不断循环
很显然,
该算法只需要一遍扫描,所以时间复杂度是O(n)
。
该算法的内存占用,主要在于那个1/ε log (εN)
个元素,所以空间复杂度是O(1/ε log (εN))
。
方案5: SpaceSaving
参考资料
- An improved data stream summary:the count-min sketch and its applications by Graham Cormode
- Approximate Frequency Counts over Data Streams by Gurmeet Singh Manku
- A.Metwally, D.Agrawal, A.El Abbadi. Efficient Computation of Frequent and Top-k Elements in Data Streams. In Proceeding of the 10th International Conference on Database Theory(ICDT), pp 398-412,2005.
- Massimo Cafaro, et al. “A parallel space saving algorithm for frequent items and the Hurwitz zeta distribution”. Proceeding arXiv: 1401.0702v12 [cs.DS] 19 Setp 2015.
- Efficient Computation of Frequent and Top-k Elements in Data Streams by Ahmed Metwally
- Finding Frequent Items in Data Streams