常见海量数据问题处理

海量数据处理:

1.top k问题

海量数据中找出最大的前k个数(或者最小的前k个数)
一般的套路是:
hash分割数据集+trie树/hash统计出词频+小顶堆
(1)使用hash的方法将数据集分成多个小的数据集
(2)使用tire树或者hash统计出每个小数据集中的词频
(3)之后用小顶堆求出数据集中频率最高k个数,最后在所有的top k中求出最中的top k

  • 看常见案例:1亿个浮点数,如何找出其中最大的1000个数?
    (1)直接排序法
    (2)局部淘汰:用一个长度为1000的数组,逐个遍历所有的数据,将最大的1000个放入数组中,时间复杂度O (n+m^2)
    ————————————————————————————————————
    前两种不是很好的解决方案,面试官不会喜欢的
    (3)分治法 ,将大文件划分成若干个小文件,找出每份中最大的1000个,再从所有的最大1000个中找出最大的1000个;
    - 从文件中找出最大的1000个,利用快排的思想,将浮点数一分为二,不断的一分为二,直到左侧是最大的1000个数为止
    (4)最小堆法:读入1000个数构建小顶堆(O(mlogm)),然后,便利剩余的数,比堆顶数字大则替换掉堆顶的数字然后重新调整最小堆。然后中序遍历一下,得到最大的1000个数。O(nmlogm),空间复杂度是常数。
    ps:可以用hash法预处理一下,将重复的数字去掉,如果重复的数字很多的话,可以节省大量的运算内存空间。去重完毕后,再使用分治法和最小堆法处理。

当然,实际问题中,还是需要根据到内存大小和数据量来选择处理方法。

topk还有其应用场景:
例如 统计搜索热度最高的前10的词。
思路:(1)分治,将文件分成很多小文件(2)用hash的方法统计出每个小文件中词的频率(3)建容量为10 的小顶堆:首先输入前位数,遍历剩余的文件,比堆顶大则替换,最终得到最大的10个数。(4)合并结果后再用最小堆找出前十的词。

2.重复问题

找出大数据量下的重复元素或者去重的需求,一般用位图(bitmap)的方式实现。

如题:一个文件,里面存储了大量的电话号码,每个号码都是8位的数字,请统计不同号码的个数。

解:8位数字能表示最大的数字是99999999,如果每个数字对应位图中的一位,需要申请99999999位即约99Mbit的内存,折合99/8MB的内存。
(2)遍历号码,在对应的数组下标置为1,遍历完文件后;位图上置为1的下标就表示该号码存在。输出置为1的个数即可。

类似问题:
1)10亿个整数,只有一个数重复出现过,O(n)的时间复杂度内找出这个数
思路:
1.bitmap法:申请一个长度为Int最大值的bit数组,按行读文件,若该位置已经是1了,你则说明重复了。
2.分治法,使用hash份成1000份小文件,重复的数肯定会分在一个文件里。分别用hashMap处理每个小文件。

2)给两个文件,每个文件存了50亿的url,每个url占64Byte,在O(n)时间里找出两个文件相同的url
思路:(1)将每个urlhashcode % 1000,切割成很多小文件;(2)hash后,相同的url肯定都落到了相同的小文件中。(3)遍历a0文件,存入hashMap,再遍历b文件,如果hashmap中存在的,则表示有相同的url。

3)给40亿个无符号整数,给定一个数,快速判断这个数是不是在这些数字里?
思路1:bitmap法
思路2:
(1)无符号整数最大是32位,也就是40亿的数字都可以表示成32位二进制的串,将给定的数字用32位二进制表示,得到一个0、1串
(2)将首位位0和首位为1的数字分成两个文件;在首位与给定数一致的文件里再分次位为0和次位为1两个文件,直到最后找到这个数为止 (O(lgn))

3.排序问题

示例:9亿个不重复的8位数,请排序:
思路:最大数位99999999 ,位图法,申请一个可以包含8位整数个的数组,长度为1亿的bit数组,挨个读文件,读出数字,在对应的位上置为1。遍历整个数组,将bit为1的下标存入文件,最终得到了排序的结果。

布隆过滤器:

思想:
准备条件:
1.长度为m的bit数组
2.k个hash算法黑名单字符串集合
构建布隆过滤器
1.遍历黑名单集合
2.每一条数据计算k个hash函数,hashcode取m模后落到数组的某一位置为1
3.循环遍历集合后m长度的数组中就有若干为置为了1
检测字符串str
1.一次计算k个hash函数,对m取模
2.如果没有落到值为1的位置,则肯定不是黑词
3.如果每个结果都落到了值为1的位置,则有可能是黑词。(对于结果不准的情况,可以将可能的值再精确匹配一次)

image.png

几个实例:

  • 1.一个8g的文件,每一行是一个整型数字,服务器的内存是2g,怎么得到文件里重复出现的数字
    思路1:位图法,申请一个长度为最大整数的bit数组,挨个读取文件,将对应数字下标的数组标记为1,如果遇到该位置已经是1的,输出下标到文件中。这就是重复了的数字。
    思路2:分治法,将数字取模%1000,分为1000个小文件,每个文件处理,将数字存入hashmap,输出重复的数字到文件中。因为是取模操作,所以重复的数字肯定是落到了同一个文件中的。

  • 思路拓展

  • (1)很多数,超过了整数的界限,其中有一个数出现过一次,其余都是出现过两次,找出这个数?
    思路:遍历,将所有的数做异或,遍历结束后,出现两次的数都抵消了,剩下的数就是自己了。(自己与自己做异或运算是0)
    case:举个栗子:2 3 4 2 3
    所有数字依次异或运算:2 xor 3 xor 4 xor 2 xor 3 = (2 xor 2) xor (3 xor 3) xor 4= 0 xor 0 xor 4 = 4

  • (2)一年的全国高考考生人数为500 万,分数使用标准分,最低100 ,最高900 ,没有小数,要求对这500 万元素的数组进行排序。
    思路:桶排序,因为分数分布在100~900之间,创建801个桶并编号,遍历500个数,丢入到对应的桶中,这样就可以排出所有人的分数了。
    注:与位图法有点类似,就是:下标=数字值。

你可能感兴趣的:(常见海量数据问题处理)