【面试被虐】如何只用2GB内存从20亿,40亿,80亿个整数中找到出现次数最多的数?

这几天小秋去面试了,不过最近小秋学习了很多和位算法相关文章,例如面试

【面试现场】如何判断一个数是否在40亿个整数中?算法

【算法技巧】位运算装逼指南数据结构

对于算法题仍是有点信心的,,,,因而,发现了以下对话。函数

20亿级别

面试官:若是我给你 2GB 的内存,而且给你 20 亿个 int 型整数,让你来找出次数出现最多的数,你会怎么作?工具

小秋:(嗯?怎么感受和以前的那道判断一个数是否出如今这 40 亿个整数中有点同样?但是,若是仍是采用 bitmap 算法的话,好像没法统计一个数出现的次数,只能判断一个数是否存在),我能够采用哈希表来统计,把这个数做为 key,把这个数出现的次数做为 value,以后我再遍历哈希表哪一个数出现最多的次数最多就能够了。学习

面试官:你能够算下你这个方法须要花费多少内存吗?开发工具

小秋:key 和 value 都是 int 型整数,一个 int 型占用 4B 的内存,因此哈希表的一条记录须要占用 8B,最坏的状况下,这 20 亿个数都是不一样的数,大概会占用 16GB 的内存。大数据

面试官:你的分析是对的,然而我给你的只有 2GB 内存。优化

小秋:(感受这道题有点类似,不过不知为啥,没啥思路,这下凉凉),目前没有更好的方法。设计

面试官:按照你那个方法的话,最多只能记录大概 2 亿多条不一样的记录,2 亿多条不一样的记录,大概是 1.6GB 的内存。

小秋:(嗯?面试官说这话是在提示我?)我有点思路了,我能够把这 20 亿个数存放在不一样的文件,而后再来筛选。

面试题:能够具体说说吗?

小秋:刚才你说,个人那个方法,最多只能记录大概 2 亿多条的不一样记录,那么我能够把这 20 亿个数映射到不一样的文件中去,例如,数值在 0 至 2亿之间的存放在文件1中,数值在2亿至4亿之间的存放在文件2中....,因为 int 型整数大概有 42 亿个不一样的数,因此我能够把他们映射到 21 个文件中去,如图

显然,相同的数必定会在同一个文件中,咱们这个时候就能够用个人那个方法,统计每一个文件中出现次数最多的数,而后再从这些数中再次选出最多的数,就能够了。

面试官:嗯,这个方法确实不错,不过,若是我给的这 20 亿个数数值比较集中的话,例如都处于 1~20000000 之间,那么你都会把他们所有映射到同一个文件中,你有优化思路吗?

小秋:那我能够先把每一个数先作哈希函数映射,根据哈希函数获得的哈希值,再把他们存放到对应的文件中,若是哈希函数设计到好的话,那么这些数就会分布的比较平均。(关于哈希函数的设计,我就不说了,我这只是提供一种思路)

40亿级别

面试官:那若是我把 20 亿个数加到 40 亿个数呢?

小秋:(这还不简单,映射到42个文件呗)那我能够加大文件的数量啊。

面试官:那若是我给的这 40 亿个数中数值都是同样的,那么你的哈希表中,某个 key 的 value 存放的数值就会是 40 亿,然而 int 的最大数值是 21 亿左右,那么就会出现溢出,你该怎么办?

小秋:(那我把 int 改成 long 不就得了,虽然会占用更多的内存,那我能够把文件分多几份呗,不过,这应该不是面试官想要的答案),我能够把 value 初始值赋值为 负21亿,这样,若是 value 的数值是 21 亿的话,就表明某个 key 出现了 42 亿次了。

这里说明下,文件仍是 21 个就够了,由于 21 个文件就能够把每一个文件的数值种类控制在 2亿种了,也就是说,哈希表存放的记录仍是不会超过 2 亿中。

80亿级别

面试官:反应挺快哈,那我若是把 40 亿增长到 80 亿呢?

小秋:(我靠,这变本加厉啊).........我知道了,我能够一边遍历一遍判断啊,若是我在统计的过程当中,发现某个 key 出现的次数超过了 40 亿次,那么,就不可能再有另一个 key 出现的次数比它多了,那我直接把这个 key 返回就搞定了。

面试官:行,这次面试到此结束,回去等通知吧。

总结

今天这篇文章主要讲了大数据处理相关的一些问题,后面可能还会给你们找一些相似,但处理方式不一样的题勒,你们若是以为不错,不妨:

若是你以为这篇内容对你挺有启发,为了让更多的人看到这篇文章:不妨

一、点赞,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)

二、关注我和专栏,让咱们成为长期关系

三、关注公众号「苦逼的码农」,主要写算法、计算机基础之类的文章,里面已有100多篇原创文章

公众号主页
大部分的数据结构与算法文章被各类公众号转载相信必定能让你有所收获
我也分享了不少视频、书籍的资源,以及开发工具,欢迎各位的关注,第一时间阅读个人文章。

相关文章
相关标签/搜索