作为一名大数据开发工程师,求职面试时,关于海量数据处理的问题时常会遇到。
张工是一名程序员,最近到某知名互联网公司面试,面试官提出这样的一个问题:
有两份文件a、b ,各存放 50 亿个 URL,每个 URL 各占 64字节,内存限制是 4G。请问如何找出这两份文件中共同的 URL?
张工一时没有回答上来,面试官说:你从事大数据开发有三年多了,这道题目应该难不倒你啊。
被面试官这么一说,张工都不好意思了。
其实面试官问这个问题无非就是考察两点:
考察求职者对分治策略思想是否了解?如何利用分治策略思想解决不同场景的问题能力?解决这个问题前,我们先来看看什么是分治策略思想。
什么是分治策略( Divide and Conquer )
将原始问题划分或者归结为规模较小的子问题递归或迭代求解每个子问题(独立求解)将子问题的解综合得到原问题的解注意:
子问题与原始问题性质完全一样子问题之间可彼此独立地求解递归停止时子问题可直接求解(子问题足够小,我们可以有直接的求解算法)
了解了分治策略思想了,我们再回过头来看看面试官提出的题目:
每个 URL 占 64字节,那么 50 亿个 URL占用的空间大小约为 320GB。
5, 000, 000, 000 * 64B ≈ 5GB * 64 = 320GB
由于内存大小限制,只有 4G,我们不可能一次性把所有 URL 加载到内存中处理,根据分治策略思想,我们可以把一份文件中的 URL 按照某个特征划分为多个小文件,使得每个小文件大小不超过 4G,这样就可以把这个小文件读到内存中进行处理了。
解决方案
首先遍历 a文件,对遍历到的 URL 求 hash(URL) % 1000 ,根据计算结果把遍历到的 URL 存储到 a0, a1, a2, ..., a999小文件中,这样每个文件大小约为 300MB。对此,你可能有疑问,为什么是1000?而不是2000,或是3000,这主要根据内存大小和要分治的文件大小来计算,我们就大致可以把320G大小分为1000份,这样每份文件大小约300MB。
接着,我们使用同样的方法遍历b 文件,同样把遍历到的 URL 分别存储到 b0, b1, b2, ..., b999 小文件中。
经过这样处理过后,所有可能相同的 URL 都在对应的小文件中,即 a0 对应 b0,a1 对应 b1, ..., a999 对应 b999,不对应的小文件不可能有相同的 URL。
那么接下来,我们只需要求出这 1000 对小文件中每一对相同的 URL 就好了。
接着遍历 ai( [0,999] ),把 URL 存储到一个 HashSet 集合中。然后遍历 bi 中每个 URL,检查在 HashSet 集合中是否存在,若存在,说明这就是我们要找的共同 URL,我们可以把这些 URL 保存到一个单独的文件中。
总结
分而治之,进行哈希取余;对每个子文件进行 HashSet 统计。本文采用时间换取空间,关于分治策略思想,平时工作中要注意总结和积累,查漏补缺,不断完善自己的知识体系。
由于笔者水平有限,文中纰漏之处在所难免,权当抛砖引玉,不妥之处,请大家批评指正。
不知对此你有没有其他更好的解决方案,欢迎交流!
如果觉得《面试官:你都工作三年了 连这道题都不会 你平时工作都做什么啊》对你有帮助,请点赞、收藏,并留下你的观点哦!