每日算法总结——大数据问题的解题技巧、题目练习

大数据题目的解题技巧

  1. 哈希函数可以把数据按照种类均匀分流
  2. 布隆过滤器用于集合的建立与查询,并可以节省大量空间
  3. 一致性哈希解决数据服务器的负载管理问题
  4. 利用并查集结构岛问题的并行计算
  5. 位图解决某一范围上数字的出现情况,并可以节省大量空间
  6. 利用分段统计思想、并进一步节省大量空间
  7. 利用堆、外排序来做多个处理单元的结果合并

关于大数据问题:

  • 面试场合大数据问题还是比较常见的,同一个大数据问题可能可以使用多种解题方法,具体使用什么方法在于我们跟面试官聊到什么程度
  • 大数据问题相对开放一些,拿到这类题目时,需要向面试官询问清楚系统限制、有哪些资源可以用、能否接受预期失误率等等,提问的出发点就是上面七个技巧,看看面试官到底想问哪种方法
  • 要培养好自己询问问题的能力,这种能力在面试场合比较重要,因为在实际的应用场景中,很多问题确实就是模棱两可的,需要我们搞清楚问题的本质、抽象化问题,很多面试官都比较看重这个能力(看你会不会问问题,以此来判断实际工作中会不会把问题搞清楚)

1~4的问题之前已经介绍过了,下面介绍剩下的。

题目1、某一范围上数字的出现问题

题目描述:32位无符号整数的范围是0~4,294,967,295,现在有一个正好包含40亿个无符号整数的文件,所以在整个范围中必然存在没出现过的数。可以使用最多1GB的内存,怎么找到所有未出现过的数?

解题思路

  • 32位无符号整数一共有232个,我们可以直接准备一个长度为为232位图,初始为0,位图的大小为232/8=229byte≈500MB,遍历所有数,出现过就把位图对应的位置标为1。

  • 最后位图上为0的位置就是未出现的数。

【进阶】
内存限制为3MB,但是只用找到一个没出现过的数即可。

  • 显然,如果限制使用的空间非常少的话,需要的时间将会很大,典型的以时间换空间

解题思路(分段统计思想

  • 我们可以最大限度的把 0~232-1 这个范围分成n个小范围,同时在内存中,使用nint记录每个范围中数字出现的次数
    • 必须保证 n = 2m,以至于它能把 232 次方整除,得到每个范围都是相同大小的。
    • 在给定的内存限制下,n越大越好
  • 比如内存限制为3MB,我们可以计算出n的最大值 3M/4(一个int占4个字节)≈ 700+,所以n最大只能取29=512,把整个范围域划分为512个子范围(int[] arr = new int[512]),每个范围有 232/29=223 个数。
  • 每个int都负责记录对应范围上数出现的次数
    • 比如取到一个数为10,由于0 < 10 < 223,所以arr[0]++
    • 一直遍历完所有的数
  • 一定存在i,使得arr[i] < 232,由于只要找到一个没出现过的数,所以只用找到一个i即可
  • arr[i]对应的范围再次分成512个子范围,再次统计每个范围上数出现的次数(不在该范围的数直接丢掉,不做任何处理)
  • 重复上述过程,直到可以确定一个没出现过的数

当内存限制非常小,只为有限几个变量时,上述过程直接就变成了二分法

题目2、寻找重复项/Top K

题目描述:有一个包含100亿个URL的大文件,假设每个URL占用64B,请找出其中所有重复的URL

解题思路

  1. 利用之前所讲的哈希分流方法,把整个大文件分成多个小文件,然后在每个小文件中找重复的URL,最后整合即可。
  2. 利用之前所讲的布隆过滤器方法,依次将每个URL通过多个哈希函数映射到整个位图上,同时判断是否能透过布隆过滤器,由此可知URL是否是重复出现的。这种方法也会有一定失误率,有些不重复的URL也可能会被判定为重复。

【补充】
某搜索公司一天的用户搜索词汇是海量的(百亿数据量),请设计一种求出每天热 Top100 词汇的可行办法

解题思路

  • 主要利用一种堆上堆的结构
  • 首先还是把所有的搜索词汇使用哈希函数进行分流,整个大文件分成100个小文件
  • 将每个小文件中的所有词汇放入一个大根堆(以搜索次数为排序标准)中,再将所有大根堆堆顶的词汇(一共100个)都取出,并放入一个额外的大根堆中(容量为100)。
  • 从这个额外的大根堆中依次取出堆顶的词汇,每取出一个词汇,就将该词汇原本所在大根堆的堆顶词汇取出并补充道额外大根堆中
  • 从额外大根堆中取出的前100个词汇即为 Top100 词汇。

题目3、寻找某一范围上出现两次的数

题目描述:32位无符号整数的范围是0~4294967295,现在有40亿个无符号整数,可以使用最多1GB的内存,找出所有出现了两次的数。

解题思路:可以利用哈希分流的思想,把这包含40亿个无符号整数的大文件分成多个小文件,在每个小文件中查找出现了两次的数,然后整合。

【补充】
可以使用最多10MB的内存,怎么找到这40亿个整数的中位数?

解题思路(分段统计思想)

  • 这题其实和题目1的思想一样,首先就是把 0~232-1 这个范围进行分段,每一段要使用一个int统计在该段中的数出现的次数,分段的数量当然是要保证是2的次方数(为了能整除232),同时在10MB的限制下越多越好
  • 由 10MB/4B = 2500 可得,分段的最大数量是 211 = 2048,所以每一段包含 232/211 = 221 个数
  • 遍历这40亿个数,需要确定每个数在哪个范围里,判定方法就是:该数/221,然后取整,就会得到范围的左边界,然后把范围对应的int加一。
  • 由于有40亿个数,所以中位数肯定是第 40亿/2 个,所以通过累加求和的方式,确定中位数哪个范围里,把该范围再次细化分段,重复……直到找到中位数。

题目4、大数据排序

题目描述:给你一个10G的文件,文件中都是有符号整数,但是无序,只有5G内存,请你把这个文件变成有序的。

解题思路:也是**分段排序**,准备一个小根堆

  • 小根堆容量的确定:一个有符号整数,我们不仅要记录该整数,还要记录该整数的词频,所以需要两个int,也就是8byte的空间,但实际上我们可能还需要一些额外的空间来存储一些其他的变量,所以假定大根堆每个条目需要16byte的空间,则大根堆的最大容量为 5GB/16B = 5 * 226,取2的次方数即 228
  • 每一段都是一个范围,我们是按照从小数到大数的顺序进行排序,比如最小的范围就是 [-231,-231 + 227 - 1],我们就遍历这10G的大文件,把所有在这个范围中的数放入小根堆中,重复的数就将其词频加一,这样这个范围内的数就排序完了,接着排序 [-231 + 227,-231 + 227 * 2 - 1] 范围内的数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值