对该算法程序编写以及踩坑点很熟悉的同学可以直接跳转到代码模板查看完整代码
只有基础算法的题目会有关于该算法的原理,实现步骤,代码注意点,代码模板,代码误区的讲解
非基础算法的题目侧重题目分析,代码实现,以及必要的代码理解误区
维护一个集合,支持如下几种操作:
I x,插入一个数 x;
Q x,询问数 x 是否在集合中出现过;
现在要进行 N 次操作,对于每个询问操作输出对应的结果。
输入格式
第一行包含整数 N,表示操作数量。
接下来 N 行,每行包含一个操作指令,操作指令为 I x,Q x 中的一种。
输出格式
对于每个询问指令 Q x,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes,否则输出 No。
每个结果占一行。
数据范围
1≤N≤105
−109≤x≤109
输入样例:
5
I 1
I 2
I 3
Q 2
Q 5
输出样例:
Yes
No
题目来源:https://www.acwing.com/problem/content/842/
若数x与数y产生哈希冲突,共同映射到小数k
顺延操作: 对于Hash[i]来说,当i++到达N-1时
并不意味着整个Hash[]存储满了
而是Hash[k]之后存储满了,k之前可能还有存储空间
所以每次i++到达N时,i=0,再重头找
顺延次数:
由于Hash[]本身数组长度是所有个数的2~3倍
所以%N后一般只需要顺延2~5个哈希表格子
耗时为O(1)
先到达Hash[(x%N+N)%N]
若Hash[(x%N+N)%N] == x,则查询到x确实存在
若Hash[(x%N+N)%N] != x,则向后顺延查表,i++, i%N;
若在查询到x之前,先遇到了Hash[i] == 0;则说明x不存在于哈希表中
//先找一个2~3倍的质数作为数组长度
int N = 0;
for(int i=200000; i++){
int flag = 1;
for(int j=2; j*j<i; j++){
if(i%j == 0){
flag = 0;
break;
}
}
if(flag){
N = i;
}
}
int Hash[N];
//空表置为无穷:
memset(Hash,0x3f,sizeof(h));
//无穷表示空点:
int ept = 0x3f3f3f;
int find(int x){
int k = (x%N + N)%N;
while(h[k] != ept && h[k] != x){
k++;
//重头查找,肯定会停止,因为n个数插入2*n个格子,必然有空,或者找到自己
if(k == N) k = 0;
}
//返回的可能是空格子,也可能是自己在格子中
return k;
}
if (Hash[find(x)] == ept)
cout<<x<<"不存在"<<endl;
else
cout<<x<<"存在"<<endl;
void insert(int x){
//k可能是第一个空,也可能是第一个x
int k = find(x);
if (Hash[k] == ept) Hash[k] = x;
}
掌握开放寻址法哈希表,主要掌握应对哈希冲突的find()函数即可
为什么星期6博客只更新了一篇?
昨天了5个小时,感觉台球水平也到达了练气境中期,hh,有了球感之后不怎么需要瞄准了,希望下周保持
看完本篇博客,恭喜已登 《练气境-中期》
距离登仙境不远了,加油