大数据面试题—数据结构

1)给⼀个超过100G⼤⼩的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
2)与上题条件相同,如何找到top K的IP?如何直接⽤Linux系统命令实现?
3)给定100亿个整数,设计算法找到只出现⼀次的整数
4)给两个⽂件,分别有100亿个整数,我们只有1G内存,如何找到两个⽂件交集
5)1个⽂件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数
6)给两个⽂件,分别有100亿个query,我们只有1G内存,如何找到两个⽂件交集?分别给出精确算法和近似算法
7)如何扩展BloomFilter使得它⽀持删除元素的操作?
8)如何扩展BloomFilter使得它⽀持计数操作?
9)给上千个⽂件,每个⽂件⼤⼩为1K—100M。给n个词,设计算法对每个词找到所有包含它的⽂件,你只有100K内存
10有⼀个词典,包含N个英⽂单词,现在任意给⼀个字符串,设计算法找出包含这个字符串的所有英⽂单词


解决问题:

1)给⼀个超过100G⼤⼩的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?

答:主要思想是:如果给一个大文件,首先考虑 位图和布隆,如果处理不了的话,考虑用哈希切分的方法。

在这我们用哈希切分:采用哈希切割将ip相同的文件用散列函数(ip地址看成是字符串转为int类型)都映射到同一个文件中,再一次统计每个文件ip的个数,求出最多的,如果一个ip出现的次数特别多,切割之后还是无法加载到内存中,我们可以再对这个文件进行切割(普通切割)分成若干个小文件,最后将小文件的结果汇总比较,求出出现次数最多的ip地址。

这里写图片描述

2)与上题条件相同,如何找到top K的IP?如何直接⽤Linux系统命令实现?

答:思路分析:与上题类似,我们用哈希切分来做

1)要找到topK的ip地址,我们如果直接进行排序的话,那么有两个问题,第一就是内存放不下,第二就是效率太慢

2)所以这我们可以建一个K大小的堆(优先级队列的实质就是用小堆实现的),那么建什么堆呢?这里建小堆比较好,因为来一个数和进行堆顶的元素进行比较,然后进行向下调整,大的就下去了,因此最终统计的就是topK

Linux指令的大概思路就是:先用指令把ip切分出来(哈希切分)——>再用指令去统计次数——>然后对每个文件出现最多的次数排序(降序)——>前K个就是我们要找的topk

3)给定100亿个整数,设计算法找到只出现⼀次的整数

答:100亿个整数即占用空间400亿个字节,而42亿个字节大约占用空间4G的空间,所以400亿个字节(100亿个整数)占用空间约为40G .一次加载到内存显然是不太现实的。并且所有整数所能表示的范围为2^32,即16G。故给出的数据有很多数据是重复的.

解法1:哈希切分

与第一题类似,用哈希切分将这些数据分到100个文件 中,每个文件大约400M,
将每一个文件依次加载到内存中,利用哈希表统计出现一次的整数,
将100个文件中出现一次的整数汇总起来即为所求。

解法2:位图变形 (优先考虑)

我们熟知的位图是利用每一位来表示一个整数是否存在来节省空间,1表示存在,0表示不存在。

而上题对于所有整数而言,却有三种状态:不存在、 存在一次、存在多次。
故此,我们需要对传统位图进行扩展,用两位来表示一个整数的状态:00:不存在、
01:存在一次, 10表:存在多次,11:无效状态(舍弃)。

一个整数4个字节,32位,用两位来表示一个数的状态,则一个4个字节来表示16个数的状态。大约需要500M的内存就可以了。

4)给两个⽂件,分别有100亿个整数,我们只有1G内存,如何找到两个⽂件交集

答:

解法1:哈希切割

先对第一个文件进行切分,采用一个散列函数将相同的数都切分到同一个文件中,并对文件进行编号,在对第二个文件也采用同一个散列函数,并对文件进行编号,如果两个文件有交集一定在编号相同的文件里。这时候只需要把编号相同的文件进行比较就可以了。

方法二:位图

将第一个文件的数据映射到位图中,大约需要500M的内存,在用第二个文件中的数据进行寻找。

这里写图片描述

5)1个⽂件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

答: 其思想和第三题类似。

找次数不超过2次的整数,即01(一次),10(两次)都可以,00表示不存在,11表示(无效状态)舍弃。

6)给两个⽂件,分别有100亿个query,我们只有1G内存,如何找到两个⽂件交集?分别给出精确算法和近似算法

答:

精确算法:哈希切分

对两个文件分别进行哈希切分,使用相同的散列函数 (如 BKDRHash散列函数)将所有query转换为一个整数key ,再利用 index=key%1000就可将相同query分到同一 个文件。(index为文件下标)

将两个文件中下标相同的小文件进行对比,找出其交集。将100个文件的交集汇总起来即为所给文件的文件交集 。此种算法时间复杂度为O(N)。

近似算法:布隆过滤器

一个文件映射,一个文件去查找。但是它存在误判的情况(存在的时候),不存在的时候,准确。

首先使用相同的散列函数(如 BKDRHash散列函数)将所有 query转换为一个整数key,
又因为布隆过滤器中的每一位就可代表一个整数的存在 与否,而16G的整数用 位图512M即可表示,
将第一个文件中的整数映射到位图中去,拿第二个文件中的数字到第一个文件映射的位图中去对比,相同数字存在即为交集。此种算法时间复杂度为O(N)。

(7)(8)如何扩展BloomFilter使得它⽀持删除元素的操作?如何扩展BloomFilter使得它⽀持计数操作?

答:

因为布隆过滤器一个bit位可能对应多个元素,所以删除一个元素时不能直接删除,否则会影响其他的元素。这时候我们可以采用引用计数的方式来实现删除操作,为了记录元素出现的次数,我们不能用一个bit位来表示元素了,而是采用无符号整型(unsigned size_t)来表示,如果觉得整型浪费空间,可以用 unsigned short. 具体的实现是用一个vector将集合的元素通过几个哈希函数映射到多个位置,而每个位置的值表示有几个元素映射到这个位置上,删除的时候只需要将对应位置的值-1就可以了。

大概代码实现:

template<class K = string,  
class HashFunc1 = __HashFunc1,  
class HashFunc2 = __HashFunc2,  
class HashFunc3 = __HashFunc3,  
>  
class RefBloomFilter  
{  
public:  
    RefBloomFilter(size_t N = 1024)  
        :_size(N * 10)  
    {  
        _refbm.resize(_size);  
    }  
    void Set(const K& key)  
    {  
        size_t hash1 = HashFunc1()(key) % _size;  
        size_t hash2 = HashFunc2()(key) % _size;  
        size_t hash3 = HashFunc3()(key) % _size;  

        _refbm[hash1]++;  
        _refbm[hash2]++;  
        _refbm[hash3]++;  

        cout<<hash1<<":"<<hash2<<":"<<hash3<endl;  
    }  
    void ReSet(const K& key)  
    {  
        size_t hash1 = HashFunc1()(key) % _size;
         if( _refbm[hash1] > 0)
            _refbm[hash1]--;  
        size_t hash2 = HashFunc2()(key) % _size;
         if( _refbm[hash2] > 0)
            _refbm[hash2]--;  
        size_t hash3 = HashFunc3()(key) % _size;  
         if( _refbm[hash3] > 0)
            _refbm[hash3]--;  

    }  
    bool Test(const K& key)  
    {  
        size_t hash1 = HashFunc1()(key) % _size;  
        if (_refbm[hash1] <= 0)  
            return false;  

        size_t hash2 = HashFunc2()(key) % _size;  
        if (_refbm[hash2] <= 0)  
            return false;  

        size_t hash3 = HashFunc3()(key) % _size;  
        if (_refbm[hash3] <= 0)  
            return false;  

        return true;  
    }  
protected:  
    vector<size_t> _refbm;  
    size_t _size;  
};  

9)给上千个⽂件,每个⽂件⼤⼩为1K—100M。给n个词,设计算法对每个词找到所有包含它的⽂件,你只有100K内存

答:

这道题目用哈希表处理,就是搜索引擎的原理:倒排索引——(分词算法)

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_37941471/article/details/80295699
今日推荐