今天说一道常见的考题,也出现在腾讯面试的三面部分,很有意思。具体题目如下:文件中有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存在,所以这是去重后的结果。但是,面试官又会问你:1G的内存够分配这么多空间来实际存储40亿个QQ号吗?显然不行,你不能通过腾讯面试。方法三:文件切割显然,这是一个海量数据的问题。见过很多面面相觑的求职者,自然而然地想到了切文件的方式,避免内存过大。不过,绞尽脑汁想想,要么用文件间归并排序,要么用桶排序,反正最后都能排序。既然整理好了,就可以实现去重了,似乎一切都还好。我只能老实说,我高兴的有点早。然后,面试官又会问你:文件操作那么多,效率自然不高。显然不可能通过腾讯面试。方法四:看位图技巧!我们可以对hashmap进行优化,利用bitmap的数据结构来顺利解决时间和空间上的问题。在很多实际项目中,经常会用到位图。看了很多组件的源码,发现很多地方都有bitmap的实现。位图图如下:这是一个unsignedchar类型。可以看到一共有8位,取值范围是[0,255]。上面unsignedchar的值为255,可以识别0~7这几个数字存在。同理,下面的unsignedchar类型的值为254,其对应的含义是:1~7的数字存在,但是0不存在:可见一个unsignedchar类型的数据可以识别这8个数字0~7有无整数。依次类推:一个unsignedint类型的数据可以识别0到31的32个整数有无,两个unsignedint类型的数据可以识别0到63的64个整数有无。显然,可以推导出512MB的大小足以识别所有QQ号的存在。请注意:QQ号码的理论最大值为2^32-1,约为43亿。接下来的问题很简单:用512MB的unsignedint数组记录QQ号在文件中的存在,形成位图,例如:bitmapFlag[123]=1bitmapFlag[567]=1bitmapFlag[123]=1bitmapFlag[890]=1其实就是:bitmapFlag[123]=1bitmapFlag[567]=1bitmapFlag[890]=1然后从小到大遍历所有正整数(4字节)。当bitmapFlag值为1时,表示该号码存在。而且,从上面的过程可以看出,去重是自动实现的。很明显,这个方法可以通过腾讯的面试。扩展练习1文件中有40亿个不同的QQ号码,请设计一个算法对QQ号码进行排序,内存限制为1G。很明显,直接用位图标记这40亿个QQ号的存在,然后把正整数从小到大遍历。当bitmapFlag的值为1时,输出该值。输出后的正整数序列就是排序后的结果。请注意,不同的QQ号码必须有40亿个限制。通过位图记录,客观上自动完成排序功能。扩展练习2文件中有40亿个不同的QQ号,求这些QQ号的中位数,内存限制为1G。我知道有些刷题经验丰富的人首先想到的肯定是用桩或者锉切,这明显是书本错误。直接用位图排序,当场取中位数。扩展练习3文件中有40亿个不同的QQ号码。求出这些QQ号的top-K,内存限制为1G。我知道很多人都背过top-K题,信心满满。当他们想到用小顶堆或锉刀切割时,这显然是另一个书呆子式的错误。直接用位图排序,当场解决top-K问题。扩展练习4文件中有80亿个QQ号,尝试判断里面是否有相同的QQ号,内存限制为1G。我知道有经验的人肯定会说,直接位图吧。然而,又错了。根据包含排除原理可知,由于QQ号的数量约为43亿(理论值2^32-1),所以80亿个QQ号中必然存在相同的QQ号。对于海量数据的问题,要具体问题具体分析,不要凭眉毛胡子去把握。有些人根本不刷题,绝对不会。有的人刷完题不去想,不懂得变通,这也是不可能的。好吧,我们先说吧。我们也会一步一个脚印,力求在每篇文章中把一件事讲清楚,希望大家看完有所收获,心情愉快。
