2024年算法基础提升——哈希函数和并查集(C++,快点来白嫖

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

}

string getRandomKey() {
    int random = rand() % size;     // get [0, size-1]
    return indexKeyMap.at(random);  // we can also use indexKeyMap[random] instead
}

};
int main()
{
RandomPool randomPool;
randomPool.insertKey(“A”);
randomPool.insertKey(“B”);
randomPool.insertKey(“C”);
cout << “=Insert key=” << endl;
cout << "keyIndexMap: " << endl;
for (auto& it : randomPool.keyIndexMap) {
cout << it.first << ": " << it.second << endl;
}
cout << "indexKeyMap: " << endl;
for (auto it = randomPool.indexKeyMap.begin(); it != randomPool.indexKeyMap.end(); ++it) {
cout << it->first << ": " << it->second << endl;
}
cout << “=Random key=” << endl;
string randomKey1 = randomPool.getRandomKey();
string randomKey2 = randomPool.getRandomKey();
string randomKey3 = randomPool.getRandomKey();
cout << "key1: " << randomKey1 << “\n” << "key2: " << randomKey2 << “\n” << "key3: " << randomKey3 << endl;

cout << "===================Delete key===================" << endl;
randomPool.deleteKey("A");  // delete "A"
cout << "keyIndexMap: " << endl;
for (auto& it : randomPool.keyIndexMap) {
    cout << it.first << ": " << it.second << endl;
}
cout << "indexKeyMap: " << endl;
for (auto it = randomPool.indexKeyMap.begin(); it != randomPool.indexKeyMap.end(); ++it) {
    cout << it->first << ": " << it->second << endl;
}
cout << "==================After delete random key========" << endl;
string randomKey11 = randomPool.getRandomKey();
string randomKey22 = randomPool.getRandomKey();
string randomKey33 = randomPool.getRandomKey();
cout << "key1: " << randomKey11 << "\n" << "key2: " << randomKey22 << "\n" << "key3: " << randomKey33 << endl;
return 0;

}




---


##  四、布隆过滤器


### 4.1 问题介绍


布隆过滤器(Bloom Filter)实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。  
**优点:**


* 可以高效地进行查询,可以用来告诉你“某样东西一定不存在或者可能存在”
* 可以高效的进行插入(但是不能删除)
* 相比于传统的List、Set、Map等数据结构,它**占用空间更少**,因为其本身并不存储任何数据(重点)
* 适用于海量数据的查找(亿量级)


**缺点:**


* 不能提供删除操作
* 存在**失误概率**:将白名单中的内容误认为是黑名单中的(反之则不可能失误)。


例如:网络爬虫程序,为了不去爬相同的URL页面,需要记录下所有爬过的URL(极大数据量),在爬一个新的网页时,判断是否已经爬过。


### 4.2 解题思路



> 
> 参考:[http://t.csdnimg.cn/xJMl4]( )
> 
> 
> 


1. 定义一个m个空间大小的哈希表(0~m-1)。
2. 将每个URL分别通过K个不同的哈希函数,并除以m取模,将得到的所有值都在哈希表上表示出来。(例如得到1,2,4,6……那么哈希表的1,2,4,6……空间上都涂黑。如果已经涂黑了则不进行操作)。
3. 当查验一个URL是否在表上时,先将该URL通过K个哈希函数,并除以m取模,如果得到的**所有值**都在哈希表上被涂黑了,那么这个URL在表上。(例如得到1,2,4,6……但哈希表6号空间未被涂黑,说明此URL不在表上)。


重点在于如何确定m和K的值。


* ![m = -n*lnP /(ln2)^2](https://latex.csdn.net/eq?m%20%3D%20-n*lnP%20/%28ln2%29%5E2)  (其中n为样本量,P为失误率)。
* ![K = ln2 *n/m](https://latex.csdn.net/eq?K%20%3D%20ln2%20*n/m)   (其中n为样本量,m为空间)。
* ![P = (1-e^{-n*K/m})^K](https://latex.csdn.net/eq?P%20%3D%20%281-e%5E%7B-n*K/m%7D%29%5EK)  (其中P为实际失误率 )。


### 4.3 代码实现



#include
#include <unordered_map>
#include
#include <sys/time.h>
#include
#include

#define MAP_ITEMS 100000

using namespace std;

int main()
{
unordered_map<string, bool> unordermp;

timeval startTime, endTime;

//1.插入MAP_ITEMS个元素到map中
gettimeofday(&startTime, NULL);
std::string key = "https://blog.csdn.net/qq_41453285";
for(int i = 0; i < MAP_ITEMS; ++i){
	string sub_key = to_string(i);
	unordermp.insert(std::make_pair(key + sub_key, 1));
}

gettimeofday(&endTime, NULL);
long insert_time = (endTime.tv_sec - startTime.tv_sec)*1000 + (endTime.tv_usec-startTime.tv_usec)/1000;

//2.在map中查找一个元素
gettimeofday(&startTime, NULL);
if( unordermp.find(key + "10000") == unordermp.end())
	std::cout << "not found!" << std::endl;

gettimeofday(&endTime, NULL);
long find_time = endTime.tv_usec - startTime.tv_usec;

//3.估算当前key的平均大小
double key_size = key.size() + to_string(MAP_ITEMS).size()/2;

//4.打印相关信息
std::cout << "Number of members  " << "key size  " << "insert time(ms)  " << "find time(us)  " << std::endl;
std::cout << left << setw(19) << MAP_ITEMS;
std::cout << left << setw(10) << key_size;
std::cout << left << setw(17) << insert_time;
std::cout << left << setw(15) << find_time << std::endl;

}




---


## 五、一致性哈希原理


### 5.1 问题介绍



> 
> 参考:[http://t.csdnimg.cn/iKh0k]( )
> 
> 
> 




---


## 六、岛问题


### 6.1 问题介绍


![](https://img-blog.csdnimg.cn/731cb7d802234a6cb6704ec226b6b28d.png)


### 6.2 解题思路


**1. 采用感染算法:**首先从第一行开始遍历二维数组,如果发现“1”,那么递归查找和它相连接的所有“1”,并将“1”改成“2”。当下次遍历到同一个岛时,程序会发现该岛已经被标记为“2”,从而避免重复计算。


时间复杂度:![O(N*M)](https://latex.csdn.net/eq?O%28N*M%29),遍历时每个位置都会被调用1次,同时每个位置最多可能被它上下左右的4个位置递归调用4次。


**2. 采用并查集:**若数据量很大,需要并行运算求解,就不太好做了,难点在于多CPU计算结果的合并.  
 合并时要考虑将边界有重合的岛合并,但问题在于我们不知道多个重合边是否属于同一个岛。


* 考虑如下情况:有一个大C字形岛屿,被一刀切成三块了,那么在合并的时候遇到两条边,但我们不知道到底有几个岛(要合并几次)。
* 应用并查集结构,将一个岛屿构造成一个并查集,遇到相同边的时候合并进同一个并查集中,这样避免了重复合并的问题.


### 6.3 代码实现



#include
#include
#include
#include
#include
#include<unordered_map>
#include
using namespace std;

int m[100][100];

//1.感染算法实现
void infect(int i, int j, int N, int M)//可变参数只有位置i,j
{
//base case:当前位置是无效位置或者不是1,返回
if (i < 0 || i >= N || j < 0 || j >= M || m[i][j] != 1)
return;
m[i][j] = 2;
//递归感染和它连成一片的1
infect(i + 1, j, N, M);
infect(i - 1, j, N, M);
infect(i, j + 1, N, M);
infect(i, j - 1, N, M);
}
int countIslands(int N, int M)
{
if (m == NULL || m[0] == NULL)
return 0;
int res = 0;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
if (m[i][j] == 1)
{
res++;
infect(i, j, N, M);
}
}
}
return res;
}

int main()
{
int N, M;
cin >> N >> M;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < M; j++)
{
char c = getchar();
m[i][j] = c - ‘0’;
}
}
cout << countIslands(N, M);
}




---


## 七、并查集



> 
> 参考:[http://t.csdnimg.cn/1DGgy]( )
> 
> 


![img](https://img-blog.csdnimg.cn/img_convert/c45eda3cb02ab0840372092ce1110db2.png)
![img](https://img-blog.csdnimg.cn/img_convert/b8780e69826d31a98a35d0c64aa6d85a.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

CG-1715676530940)]
[外链图片转存中...(img-V0RzlWDB-1715676530940)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值