# -*- coding: utf-8 -*-
'''
Python程序员面试算法宝典---解题总结: 第9章 大数据 9.6 如何查询最热门的查询串
题目:
搜索引擎会通过日志文件把用户每次检索使用的所有查询串都记录下来,每个查询串
的长度为1~255B。
假设目前有1000万个记录(这些查询串的重复度比较高,虽然总数是1000万,但如果去除重复后,
那么不超过300万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门),
请统计最热门的10个查询串,要求使用的内存不能超过1GB。
分析:
假如内存不加以限制,最简单的方式就是用哈希去做。
统计不同查询串的出现次数。
这个问题看上去就是top K的问题。
top K问题可以用堆来实现。首先读入K个元素,
遍历后续的数字与堆顶元素比较,并调整即可。时间复杂度位O(N*LogK)。
考虑海量数据的处理方式有:
位图,布隆过滤器,哈希,倒排索引,trie树,分治。
位图用于查找去重统计,排除。
倒排索引就是搜索用的,基于哈希数组和链表实现。
trie树一般用于搜索中的自动补全。
关键:
1 书上解法
1000万个查询串,每个1~255B,最多需要
255B * 1000万 = 255B * 1000 0000 = 255 * 10000 KB
= 255 * 10 MB
= 2.55 GB
因为内存限制1Gb,所以放不下
因为大约有300万个字符串,所以字典最多占据
300 0000 * (255B + 4B) = 300 0000 * 259B = 3MB * 259 = 777MB
这样字典统计完成后,然后用top K算法来做,
具体就是维护一个大小为10的小顶堆,然后每次新来的数字和堆顶比较即可。
方法2:
分治,利用哈希函数,将字符串划分到多个文件 +
每个文件确保占用内存较小 + 每个文件获取top 10频度的字符串
+ 记录到新的文件中,统计完所有小文件,
那top 10必定在新文件记录的字符串中,然后利用小顶堆统计。
2 没有想到
是因为:
2.1 分治就是讲字符串通过哈希映射到多个足够小的小文件,
每个小文件统计top 10,最后利用小顶堆实现。
2.2 忘记了最多只有300万个,可以直接用字典记录,
最后用小顶堆实现。
2.3 trie树叶可以统计自渡船出现次数,截止到该字符串最后一个字符,
就令该字符节点中的次数累加即可。
trie树的用途: 字符串出现次数统计 + 字符串查找
参考:
Python程序员面试算法宝典
'''
def process():
pass
if __name__ == "__main__":
process()