哈希切割top K问题
- 给一个超过100G大小的log file,log中存着IP地址,设计算法找到出现次数最多的IP地址?
- 与上题条件相同。如何知道top k的ip
- 文件太大。100g,肯定不能一次加载到内存进行处理,这里就必须将文件进行切割了,可是依据哪种方法进行切割呢,假设只是从前到后等份切割的话,将文件切割n份(切割的份数依据数据所给的内存大小),第一份中假设IP地址为a出现的次数最多,第二份次数b出现的次数最多,这样比较出来,假设a比b大,那得出的结果就是IP地址为a的出现次数多,可是假设第一份中也有地址为b的IP呢,这样分割出来的文件,不能保证相同IP地址IP被分到同一文件当中,这样算出来的结果就肯定不正确了,这里我们应该想到哈希的思想,我们可以给出n个文件,(n的取值取决于给定的内存大小),将点分十进制的IP地址转化为整数,利于哈希函数(哈希函数采用直接定址法),求出IP地址所对应的文件编号,这样将所有地址分到不同的编号当中,相同的地址一定在一个同一个文件,依次遍历每个文件,统计出每个IP地址出现的次数,这样就可以找到出现次数最多的IP地址
- top K问题的解决办法我们很容易想到堆,首先,搞清楚是要出现次数最多的K个IP还是出现次数最少的K个IP,如果是最多的,可以给小堆,如果是最少的,可以给大堆;假设这里我们要的是出现次数最多的K个IP,在第一问中,我们已经求出了每个IP地址出现的次数,将这些IP地址和出现大的次数封装成一个结构体(键值对),给一个只能容纳K个键值对的小堆,在向堆中插入元素时,IP地址出现的次数作为关键码,先向堆中堆中插入K个元素,以后再插入元素时,以后再插入元素时,先与堆顶元素进行比较,如果小于堆顶元素,不做处理,如果大于,则将堆顶元素删除,将此元素重新插入堆中,当遍历完所有IP地址后,堆中保存最多的元素就是出现次数最多的K个
位图应用
- 给定100亿个整数,设计算法找到只出现一次的整数
假设这里是32位机,32位机中整形表示的最大个数为2^32,我们可以用位图来表示每个数的状态,每个数给两个比特位,00表示这个数不存在,01表示这个数存在一次,10表示这个数存在多次,这样所需空间大小为1G。符合题目要求
- 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集
与第一问一样,我们可以用位图思想,这里只需要一个比特位来表示一个数存在与否,将两个文件的数据分别映射到两个位图当中,将两个位图按位与,得出的结果就是两个文件的交集
- 1个文件有100亿的int,1G内存,设计算法找到出现次数不超过两次的所有整数
与第一问一样,也是用两个比特位表示一个数据的状态,00表示不存在,01表示出现一次,10表示出现两次,11表示出现两次以上,将每个数据映射到位图当中,最后遍历位图,就可以得出结果
布隆过滤器
- 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?分给出精确算法和近似算法
精确算法:
一个query(查询记录)字符串大概算60个字节,100亿大概600G,那么我们可以进行哈希切割,给出6000(数目越多,越不容易发生哈希冲突,结果越准确)个文件,将字符串转化为整数,采用除留取余法。将每个字符串保存到对应编号的文件中,然后在遍历第二个文件,拿到一个字符串,用相同的方法找到它所对应的文件,再到对应的文件当中找是否有与其相同的字符串,这样就找到了两个文件的交集
近似算法:
可以采用布隆过滤器。(即位图与哈希联系起来)将第一个文件当中的每一个字符串插入到布隆过滤器当中,然后在第二个文件当中遍历每一个query,到布隆过滤器中查找query是否存在,这样就可以近似找到两个文件的交集,因为布隆过滤器中查找一个元素,如果查找结果不存在,那么就一定不存在,但是如果结果为存在,其实也有可能不存在,所以这种解法为近似算法
- 如何扩展BloomFilter使得它支持删除元素的操作
可以给每一个元素分配多个比特位,例如:每个元素分配分配两个比特位,00表示不存在,01表示有一个,10表示有两个,如果要删除某个元素,给其减一,如10变为01
倒排索引
- 给上千个文件,每个文件大小为1K-100M,给n个词,设计算法对每个词找到所有包含它的文件,你只有100K内存
可以将每个文件中的词都插入到布隆过滤器中,再用所给的n个词在布隆过滤器中查找