文章目录
前言
当面对海量数据时,我们的内存是不够用的,有什么办法解决呢?
一、位图应用
1. 给定100亿个整数,设计算法找到只出现一次的整数?
分析:
100亿个整数大概需要40G 1G=2^30byte
数据出现的次数分为三种:出现0次,出现1次,出现2次以上.
使用位图改进来解决,两个位表示一个整数:00 01 10
class solution
{
public:
void set(size_t x)
{
if(_bs1.test(x)==false&&_bs2.test(x)==false)
{
_bs1.reset(x);
_bs2.set(x);
}
else if(_bs1.test(x)==false&&_bs2.test(x)==true)
{
_bs1.set(x);
_bs2.reset(x);
}
}
private:
bitset _bs1;
bitset _bs2;
}
2. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
分析:100亿个整数,肯定会有重复的,因为整数最多有42亿多个,所以一个文件用位图开500M就OK
方案一:将其中一个文件1的整数映射到一个位图中,读取另一个文件2中的整数,判断在不在位图,在就是交集.消耗500M内存
方案二:将文件1的整数映射到位图1中,将文件2的整数映射到位图2中,然后将两个位图中的数按位与.与之后为1的就是交集.消耗内存1G
3. 位图应用变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数?
分析:不超过2次的,也就是找出现1次和2次的
00表示出现0次,01表示出现1次,10表示出现2次,出现三次及以上的用11
跟第1题思路一致
二、布隆过滤器应用
1. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分别给出精确算法和近似算法
分析:query一般是一个字符串,假设平均一个query30-60byte,100亿个query大约占用300-600G
方案一:将文件1中的query映射到一个布隆过滤器,读取文件2 的query,判断在不在布隆过滤器中,在就是交集.
根据布隆过滤器的缺点,我分析方案一有没有什么缺陷呢?
交集中有些数不准确.
方案二:我们可以把文件切分成多个小文件,小文件加载到内存中.
300G-600G切1000份,就是一个文件300M-600M ,这里给的是1G内存,就可以完成.但是需要不断地互相比较.优点是1.部分数据放到内存中,2.不是暴力比较,放到set中,效率还可以
如何解决?
哈希切分
不再平均切分,哈希切分:i=hashstr(query)%1000,i是多少,query就进入第Ai/Bi的小文件中,
A和B中相同的query一定进入编号相同的Ai和Bi的文件,所以找交集就OK
2.如何扩展BloomFilter使得它支持删除元素的操作
每个位标记成计数器
三.哈希切分
给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址? 与上题条件相同,如何找到top K的IP?
统计次数,我们用map,但是数据太大,放不到内存中.
先创建1000个文件,A0-A999,读取IP计算出i=hashstr(Ip)%1000.i是多少,IP就进入对应编号的文件,这样相同的IP一定进入同一个小文件.
总结
海量数据,现实中我们经常遇到的问题,我们需要了解它,学会应用它.