湖州市网站建设_网站建设公司_产品经理_seo优化
2026/1/3 17:15:20 网站建设 项目流程

@

目录
  • 12.海量数据找相同的URL
  • 13.海量数据找高频词
  • 14.海量数据找不重复的整数
  • 15.海量数据判断数字是否存在
  • 16.海量数据找热门串
  • 17.海量数据找号码个数
  • 18.海量数据找中位数
  • 19.海量数据找前500
  • 20.海量数据问题处理总结
  • 21.heapq
  • null

12.海量数据找相同的URL

问题:给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?
 
分析:50亿个url,每个url64字节,就是320G,显然是无法一次读入内存的。因此这里需要采用分治法。
 
方案:分治法,分支方法:哈希

  1. 将AB两个文件,用相同的哈希函数,分解为1000个独立哈希值相同的小文件,这里哈希函数的设计是个重点。
  2. 哈希值不同的url必然不在序号对应的文件中,因此只要在序号对应的两个文件中进行互相匹配即可。
  3. 比较每对小文件时,可以使用hash_set。[^21]

图解详见[1]

13.海量数据找高频词

题目描述
有一个 1GB 大小的文件,文件里每一行是一个词,每个词的大小不超过 16B,内存大小限制是 1MB,要求返回频数最高的 100 个词(Top 100)。
 
思路如下:
 
首先遍历大文件,对遍历到的每个词x,执行 hash(x) % 5000,将结果为 i 的词存放到文件 ai 中。遍历结束后,我们可以得到 5000 个小文件。每个小文件的大小为 200KB 左右。如果有的小文件大小仍然超过 1MB,则采用同样的方式继续进行分解。
 
接着统计每个小文件中每个词出现频数。最简单的方式是使用 HashMap 来实现。其中key为词,value 为该词出现的频率。具体方法是:对于遍历到的词 x,如果在 map 中不存在,则执行 map.put(x, 1);若存在,则执行 map.put(x, map.get(x)+1),将该词频数加 1
 
上面我们统计了某个小文件单词出现的频数。接下来,我们可以通过维护一个小顶堆来找出所有词中出现频数最高的 100 个。具体方法是:构建一个小顶堆,堆大小为 100。遍历map,如果遍历到的词的出现次数大于堆顶词的出现次数,则用新词替换堆顶的词,然后重新调整为小顶堆,当所有小文件对应的频数map遍历结束后,小顶堆上的词就是出现频数最高的 100 个词。
 
方法总结

  1. 分而治之,进行哈希取余;
  2. 使用 HashMap 统计频数;
  3. 求解最大的 TopN 个,用小顶堆;求解最小的 TopN 个,用大顶堆。[^22]

详见[2]

14.海量数据找不重复的整数

题目描述
在 2.5 亿个整数中找出不重复的整数。注意:内存不足以容纳这 2.5 亿个整数。
 
位图法
对于这道题,我们用 2 个 bit 来表示各个数字的状态:

  • 00 表示这个数字没出现过;
  • 01 表示这个数字出现过一次(即为题目所找的不重复整数);
  • 10 表示这个数字出现了多次。
     

假设有 232 个整数,总共所需内存为 232*2b=1GB。因此,当可用内存超过 1GB 时,可以采用位图法来判断 232 (42.9亿左右)个整数。假设内存满足位图法需求,进行下面的操作:
遍历 2.5 亿个整数,查看位图中对应的位,如果是 00,则变为 01,如果是 01 则变为 10,如果是 10 则保持不变。遍历结束后,查看位图,把对应位是 01 的整数输出即可。[3]

也可以用分治法,位图及解释详见[3:1]

15.海量数据判断数字是否存在
  • 题目描述
    给定 40 亿个不重复的没排过序的 unsigned int 型整数,然后再给定一个数,如何快速判断这个数是否在这 40 亿个整数当中?[4]

  • 解答思路

  1. 方法一:分治法
    依然可以用分治法解决,方法与前面类似,就不再次赘述了。

  2. 方法二:位图法
    40 亿个不重复整数,我们用 40 亿个 bit 来表示,初始位均为 0,那么总共需要内存:4,000,000,000b≈512M。
     
    我们读取这 40 亿个整数,将对应的 bit 设置为 1。接着读取要查询的数,查看相应位是否为 1,如果为 1 表示存在,如果为 0 表示不存在。

  3. 方法三:布隆过滤器
    简单而言,布隆过滤器就是位图+一系列随机映射函数。
    使用了N个互相独立的hash函数,对每条数据都进行N次哈希,并将对应单元置为1。
    也就是说一个数字在位图当中会有好几位作为标志,只有有某一位没有打上标记,就意味这个数字不存在。
    使用多位来标记数字是为了避免哈希冲突

    • 布隆过滤器判断数据存在,那么它可能存在也可能不存在。
    • 布隆过滤器判断数据不存在,那么它必定不存在。

布隆过滤器的解法见[5],其本身的说明详见[6]

16.海量数据找热门串
  • 题目描述
    假设目前有 1000w 个记录(这些查询串的重复度比较高,虽然总数是 1000w,但如果除去重复后,则不超过 300w 个)。请统计最热门的 10 个查询串,要求使用的内存不能超过 1G。(一个查询串的重复度越高,说明查询它的用户越多,也就越热门。)
  • 解答思路
  1. 方法一:分治法
    划分为多个小文件,保证单个小文件中的字符串能被直接加载到内存中处理,然后求出每个文件中出现次数最多的 10 个字符串;最后通过一个小顶堆统计出所有文件中出现最多的 10 个字符串。

  2. 方法二:HashMap 法
    虽然字符串总数比较多,但去重后不超过 300w,因此,可以考虑把所有字符串及出现次数保存在一个 HashMap 中,所占用的空间为 300w*(255+4)≈777M(其中,4表示整数占用的4个字节)。由此可见,1G 的内存空间完全够用。

  3. 方法三:前缀树法
    方法二使用了 HashMap 来统计次数,当这些字符串有大量相同前缀时,可以考虑使用前缀树来统计字符串出现的次数,树的结点保存字符串出现次数,0 表示没有出现。

  • 总结
    前缀树经常被用来统计字符串的出现次数。它的另外一个大的用途是字符串查找,判断是否有重复的字符串等。[7]

具体解释详见[7:1],外排序详见[8][9],字典树(前缀树)详见[10][11]

17.海量数据找号码个数

题目描述
已知某个文件内包含一些电话号码,每个号码为 8 位数字,统计不同号码的个数。
 
解答思路
申请一个位图数组,长度为 1 亿,初始化为 0。然后遍历所有电话号码,把号码对应的位图中的位置置为 1。遍历完成后,如果 bit 为 1,则表示这个电话号码在文件中存在,否则不存在。bit 值为 1 的数量即为 不同电话号码的个数。
 
方法总结
求解数据重复问题,记得考虑位图法。[12]

详见[12:1]

18.海量数据找中位数

题目描述
从 5 亿个数中找出中位数。数据排序后,位置在最中间的数就是中位数。当样本数为奇数时,中位数为 第 (N+1)/2 个数;当样本数为偶数时,中位数为 第 N/2 个数与第 1+N/2 个数的均值。
 
解答思路
方法一:双堆法
维护两个堆,一个大顶堆,一个小顶堆。大顶堆中最大的数小于等于小顶堆中最小的数;保证这两个堆中的元素个数的差不超过 1。
若数据总数为偶数,当这两个堆建好之后,中位数就是这两个堆顶元素的平均值。当数据总数为奇数时,根据两个堆的大小,中位数一定在数据多的堆的堆顶。
 
方法二:分治法
对于这道题,顺序读取这 5 亿个数字,对于读取到的数字 num,如果它对应的二进制中最高位为 1,则把这个数字写到 f1 中,否则写入 f0 中。通过这一步,可以把这 5 亿个数划分为两部分,而且 f0 中的数都大于 f1 中的数(最高位是符号位)。
划分之后,可以非常容易地知道中位数是在 f0 还是 f1 中。假设 f1 中有 1 亿个数,那么中位数一定在 f0 中,且是在 f0 中,从小到大排列的第 1.5 亿个数与它后面的一个数的平均值。
对于 f0 可以用次高位的二进制继续将文件一分为二,如此划分下去,直到划分后的文件可以被加载到内存中,把数据加载到内存中以后直接排序,找出中位数。[13]

详见[13:1]

19.海量数据找前500
  • 题目描述:
    有20个数组,每个数组有500个元素,升序排列,现在在这20*500个数中找出排名前500的数。

  • 解答思路:
    保持一个20的堆,然后先将每个数组的第1个数入堆。
     
    20个元素的堆一直保持容量为20个,20个数组的最小元素可以将20个数组的第0个元素入堆,最小堆的性质,顶点为最小值。这时候得到了500个结果里的第0个结果。然后再把下一个元素入20个元素的堆,堆插入的时候会保持性质不变,最小元素依然在顶点。再取出20个元素的顶点,得到500个结果里的第1个结果。
     
    假设 [1,3,4,5,6] [2,3,4,5,6] [3,4,5,6,7]
    最小的是比较 1 2 3 得到1
    第2小的是将刚才的1替换为后面的元素3 再加上刚才的元素2 3,得到2
     
    注意这儿需要保持数来自于哪个数组,以及其在数组里的位置[14]

详见[14:1]

20.海量数据问题处理总结

处理海量数据问题,无非就是:[15]

  1. 分而治之/hash映射 + hash统计 + 堆/快速/归并排序;
  2. 双层桶划分
  3. Bloom filter/Bitmap;
  4. Trie树/数据库/倒排索引;
  5. 外排序;
  6. 分布式处理之Hadoop/Mapreduce。

另一份总结见[16]

其他海量数据处理的问题及解法见[17][18]

21.heapq

关于python当中的heapq模块详见[19]


  1. 海量数据处理面试题(1) 找出两文件种包含的相同的url ↩︎

  2. 【海量数据处理】如何从大量数据中找出高频词? ↩︎

  3. 【海量数据处理】如何在大量的数据中找出不重复的整数? ↩︎ ↩︎

  4. 如何在大量数据中判断一个数是否存在? ↩︎

  5. 如何在海量数据中判断某个数据是否存在? ↩︎

  6. 海量数据处理之Bloom Filter详解 ↩︎

  7. 如何查询最热门的查询串? ↩︎ ↩︎

  8. 排序之外部排序 ↩︎

  9. 外部排序算法总结 ↩︎

  10. 算法与数据结构基础 - 字典树(Trie) ↩︎

  11. 字典树(Trie)详解 ↩︎

  12. 如何统计不同电话号码的个数? ↩︎ ↩︎

  13. 如何从 5 亿个数中找出中位数? ↩︎ ↩︎

  14. 有20个数组,每个数组有500个元素,升序排列,现在在这20*500个数中找出排名前500的数。求时间复杂度? ↩︎ ↩︎

  15. 教你如何迅速秒杀掉:99%的海量数据处理面试题 ↩︎

  16. 海量数据处理 - 10亿个数中找出最大的10000个数(top K问题) ↩︎

  17. 十道海量数据处理面试题与十个方法大总结 ↩︎

  18. 海量数据查询 ↩︎

  19. 实践中总结出来对heapq的一点理解 ↩︎

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询