概述
大数据题目解题技巧之
- 位图解决某一范围范围上数字的出现情况,并可以节省大量空间
- 利用分段统计思想,并进一步节省大量空间
生成文件都是使用的硬盘空间
相关题目一
32位无符号整数的范围是0 ~ 4,294,967,295,现在有一个正好包含40亿个无符号整数的文件,所以在整个范围中必然存在没出现过的数。可以使用最多1GB的内存,怎么找到所有未出现过的数?
答:利用位图的思想,建立一个byte类型的数组(但是不是每一种语言类型都有byte数组,但是都有int型),每一位表示一个数有没有,有就是1,没有就是0。需要大约2 ^ 31 / 8 byte 也就是 500M空间
如果现在只有3KB的内存呢?能否找到一个没有出现过的数。
答:3kb / 4 约等于700 离512最近(2的n次方数)。所以建立int[512]的数组。而2^32/512 = 8388608,也就是每一个int数组可以记录的范围。我们将这0 ~ 4,294,967,295个数,除以8388608就知道需要放到那一个int[i]中,这个时候int[i]就加1,这样我们就知道肯定存在一个int[i]它的数值小于8388608。也即知道了缺的数字来自于那一个范围。然后你在这个范围上,继续分为512份,继续过这0 ~ 4,294,967,295,不在这一个范围上的数就不要了,在的就看是512份中的那一份,这样依次定位下去。
能否用哈希分流来做?
答:不好用,首先哈希分流所需的空间比较大,而且目前的题目也不适用此方法,因为哈希分流会将顺序打乱。
相关题目二
有一个包含100亿个URL的大文件,假设每个URL占用64B,请找出重复的URL。
答:可以用布隆过滤器(有失误率)。可以用哈希分流。
注意:要学会弄清楚问题。这是一种能力,需要将一个模糊的问题,向面试官问清楚。
补充:某搜索公司一天的用户搜索词汇量是海量的(百亿数据量),请设计一种求出每天热门Top100词汇的可行办法
答:哈希分流,得到的每一个小文件包含每个对应值以及他的词频,做成大根堆,得到Top100。将每一个小文件(目前已经是大根堆)堆顶单独拿出来,组成一个总大根堆,从总大根堆中弹出一个来打印,并且将这个堆顶属于的小文件的第二个数(将弹出来的堆顶抹去,此时第二个数就是堆顶了)加入总大根堆,以此往复。。。
相关题目三
32位无符号整数的范围是:0~4294967295, 现在有40亿个无符号整数,可以使用最多1GB的内存,找出所有出现两次的数。
答:可以使用哈希分流。也可以用位图做,此时用两个数表示一个数出现的状态。00表示0次。01表示1次。10表示2次。11表示>2次。这样需要的空间是2^32 * 2 / 8 (byte)。
补充:可以最多使用10KB的空间,怎样找到这40亿个整数的中位数?
答:用分段统计,每一段中都有次数统计,累加每一个段,找到刚超中位数的段,在这一段中继续分段,此时就是找中位数-先前所有段次数和 = 要找的位数。。。
相关题目四
一个10G的有符号int型的无序文件,怎样使用5G内存将其变成一个有序的文件。
方法1(分段统计):
- 准备工作:用小根堆,小根堆中放数值和对应的次序,按照数值排成小根堆(不是按照词频),一条记录会占用8字节,但是会有其他消耗,我们假设16字节,那么5G中存储多少条记录,5G/16向下取整为2^26。
- 因为是有符号int,所以范围是-2^32到2^32,-1,将范围等分成2^32/2^26=6块。所以先用小根堆过大文件统计最低范围上的数字也就是-2^31~-2^31+2^26-1范围。
- 如果不符合这个范围上的数字就不记录,这样小根堆就可以排起来,将这些值输出到文件,接下来看第二个范围。。。
方法2(大根堆):
- 准备工作:设立一个可以存储2^26条值的根堆,设置一个Y值意义是小于这个值的数字不让入这个大根堆即门槛,开始Y就是系统最小
- 将大文件依次存入这个2^26条数据的大根堆,大根堆中存储的数据是数据值和频次,到2^26条数据之后就不可以直接进了。
- 剩下的数据,需要比较大根堆的最顶值,如果大于就不可以进去,如果小于可以进入,进入后,弹出大根堆的堆顶,继续维持2^26条的记录。
- 遍历完,选出的这些2^26条的数据是文件中最小的2^26个值并带上频次,将每次的2^26条数据按从小到大进入文件中
- 重新遍历,此时Y=大根堆堆顶的值