今天,我们来聊一道常见的考题,也出现在腾讯面试的三面环节,非常有意思 。具体的题目如下:
文件中有40亿个QQ号码,请设计算法对QQ号码去重,相同的QQ号码仅保留一个,内存限制1G.
这个题目的意思应该很清楚了,比较直白 。为了便于大家理解,我来画个动图玩玩,希望大家喜欢 。
文章插图
能否做对这道题目,很大程度上就决定了能否拿下腾讯的offer,有一定的技巧性 , 一起来看下吧 。
在原题中,实际有40亿个QQ号码,为了方便起见,在图解和叙述时 , 仅以4个QQ为例来说明 。
方法一:排序
很自然地 , 最简单的方式是对所有的QQ号码进行排序,重复的QQ号码必然相邻 , 保留第一个,去掉后面重复的就行 。
原始的QQ号为:
文章插图
排序后的QQ号为:
文章插图
去重就简单了:
文章插图
可是,面试官要问你,去重一定要排序吗?显然,排序的时间复杂度太高了 , 无法通过腾讯面试 。
方法二:hashmap
既然直接排序的时间复杂度太高,那就用hashmap吧,具体思路是把QQ号码记录到hashmap中:
mapFlag[123] = truemapFlag[567] = truemapFlag[123] = truemapFlag[890] = true
由于hashmap的去重性质,可知实际自动变成了:mapFlag[123] = truemapFlag[567] = truemapFlag[890] = true
很显然 , 只有123 , 567 , 890存在,所以这也就是去重后的结果 。可是,面试官又要问你了:实际要存40亿QQ号码,1G的内存够分配这么多空间吗?显然不行,无法通过腾讯面试 。
方法三:文件切割
显然,这是海量数据问题 。看过很多面经的求职者,自然想到文件切割的方式,避免内存过大 。
可是,绞尽脑汁思考,要么使用文件间的归并排序,要么使用桶排序,反正最终是能排序的 。
既然排序好了,那就能实现去重了,貌似就万事大吉了 。我只能坦白地说,高兴得有点早哦 。
接着,面试官又要问你:这么多的文件操作,效率自然不高啊 。显然 , 无法通过腾讯面试 。
【腾讯三面:40亿个qq号码如何去重复登录】
方法四:bitmap
来看绝招!我们可以对hashmap进行优化,采用bitmap这种数据结构,可以顺利地同时解决时间问题和空间问题 。
在很多实际项目中 , bitmap经常用到 。我看了不少组件的源码,发现很多地方都有bitmap实现 , bitmap图解如下:
文章插图
这是一个unsigned char类型,可以看到,共有8位,取值范围是[0, 255],如上这个unsigned char的值是255,它能标识0~7这些数字都存在 。
同理,如下这个unsigned char类型的值是254 , 它对应的含义是:1~7这些数字存在,而数字0不存在:
文章插图
由此可见,一个unsigned char类型的数据,可以标识0~7这8个整数的存在与否 。以此类推:
- 一个unsigned int类型数据可以标识0~31这32个整数的存在与否 。
- 两个unsigned int类型数据可以标识0~63这64个整数的存在与否 。
显然,可以推导出来:512MB大小足够标识所有QQ号码的存在与否,请注意:QQ号码的理论最大值为2^32 - 1,大概是43亿左右 。
接下来的问题就很简单了:用512MB的unsigned int数组来记录文件中QQ号码的存在与否,形成一个bitmap,比如:
bitmapFlag[123] = 1bitmapFlag[567] = 1bitmapFlag[123] = 1bitmapFlag[890] = 1
实际上就是:bitmapFlag[123] = 1bitmapFlag[567] = 1bitmapFlag[890] = 1
然后从小到大遍历所有正整数(4字节),当bitmapFlag值为1时 , 就表明该数是存在的 。而且,从上面的过程可以看到,自动实现了去重 。显然 , 这种方式可以通过腾讯的面试 。
文章插图
扩展练习一
文件中有40亿个互不相同的QQ号码 , 请设计算法对QQ号码进行排序 , 内存限制1G.
推荐阅读
- 腾讯要怎么开通会员,腾讯会员怎么开通会员
- 华为市值大概多少,华为和腾讯哪个市值高
- 腾讯的保存在哪里,腾讯文件存储路径
- 腾讯弹幕怎么设置
- 腾讯爱奇艺又“撞档”,新剧上线仅隔2天,都是超强阵容难抉择!
- 腾讯会议怎么加入开会,腾讯会议怎么加入别人的预定会议
- 怎么给别人充腾讯会员
- 腾讯、爱奇艺、优酷推出“巅峰之作”进入了白热化,又是谁能拔得头筹?
- 腾讯会议室怎么创建会议室,腾讯会议周期性会议室如何使用
- 企业qq停止服务了腾讯qq会停止吗 企业qq停止运营和个人qq有关系吗