数据结构
如Bloom filter/Hash/bit-map/堆/数据库或倒排索引/trie树,针对空间,无非就一个办法:大而化小,分而治之(hash映射)
步骤:
- 分而治之/hash映射:针对数据太大,内存受限,只能把大文件化成(取模映射)小文件
- hash_map统计:当大文件转化了小文件,那么我们便可以采用常规的hash_map(key,value)来进行频率统计。
- 堆/快速排序:统计完了之后,便进行排序(可采取堆排序),得到次数最多的key。
MapReduce原理(如统计一句话中单词出现的次数)
MapReduce是一种计算模型,简单的说就是将大批量的工作(数据)分解(MAP)执行,然后再将结果合并成最终结果(REDUCE)。这样做的好处是可以在任务被分解后,可以通过大量机器进行并行计算,减少整个操作的时间。说白了,Mapreduce的原理就是一个归并排序。
海量日志数据,提取出某日访问百度次数最多的那个IP
分而治之/hash映射:针对数据太大,内存受限,只能是把大文件化成(取模映射)小文件;按照IP地址的Hash(IP)%1000值,把海量IP日志分别存储到1000个小文件中。这样,每个小文件最多包含4MB个IP地址
hash_map统计:当大文件转化了小文件,那么我们便可以采用常规的hash_map(ip,value)来进行频率统计。
堆/快速排序:统计完了之后,可以得到1024个小文件中的出现次数最多的IP,再依据常规的排序算法得到总体上出现次数最多的IP;
10亿个数中找出最大的10000个数
先拿10000个数建最小堆,然后一次添加剩余元素,如果大于堆顶的数(10000中最小的),将这个数替换堆顶,并调整结构使之仍然是一个最小堆,这样,遍历完后,堆中的10000个数就是所需的最大的10000个。建堆时间复杂度是O(mlogm),算法的时间复杂度为O(nmlogm)(n为10亿,m为10000)。
优化的方法:可以把所有10亿个数据分组存放,比如分别放在1000个文件中。这样处理就可以分别在每个文件的10^6个数据中找出最大的10000个数,合并到一起在再找出最终的结果。
给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
假如每个url大小为10bytes,那么可以估计每个文件的大小为50G×64=320G,远远大于内存限制的4G,所以不可能将其完全加载到内存中处理,可以采用分治的思想来解决。Step1:遍历文件a,对每个url求取hash(url)%1000,然后根据所取得的值将url分别存储到1000个小文件(记为a0,a1,…,a999,每个小文件约300M);Step2:遍历文件b,采取和a相同的方式将url分别存储到1000个小文件(记为b0,b1,…,b999);巧妙之处:这样处理后,所有可能相同的url都被保存在对应的小文件(a0vsb0,a1vsb1,…,a999vsb999)中,不对应的小文件不可能有相同的url。然后我们只要求出这个1000对小文件中相同的url即可。Step3:求每对小文件ai和bi中相同的url时,可以把ai的url存储到hash_set/hash_map中。然后遍历bi的每个url,看其是否在刚才构建的hash_set中,如果是,那么就是共同的url,存到文件里面就可以了。
给定N篇文档K个关键词,输出每个关键词匹配的文档
N和K都很大的情况下,使用Trie树
Trie 的强大之处就在于它的时间复杂度。它的插入和查询时间复杂度都为 O(k) 。而且其中的K为单词的长度。同时其不会产生任何碰撞,所以其最大的时间复杂度为O(k)。但是当字符串的重复率较大,数据较多时,这个时间复杂差的还是比较大的。简单地说,Trie就是直接定址表和树的结合的产物。