题面
输入样例
5
I 1
I 2
I 3
Q 2
Q 5
输出样例
Yes
No
题解1
- 拉链法 : 开一个大于N的数组,模N求出的 k 就是每个数哈希之后的位置,如果多个值在同一个位置,就拉出一条单链表,每个数组的开头就是单链表的头节点
- 对于删除操作,我们可以不需要真正删除,直接新开一个bool数组标记一下即可
代码1
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100003; //取大于1e5的第一个质数
int h[N]; //开一个槽,每个槽拉出一个链,槽作为链表的头节点
int e[N], ne[N], idx;
//数组模拟链表 头插入(之前链表有写过)
void insert(int x) {
int k = (x % N + N) % N; //让负数的余数变为正数
e[idx]=x;
ne[idx]=h[k];
h[k]=idx;
idx++;
}
bool find(int x) {
int k = (x % N + N) % N;
for(int i=h[k];i!=-1;i=ne[i]){
if(e[i]==x){
return true;
}
}
return false;
}
int main() {
memset(h,-1,sizeof h);
int n;
cin >> n;
while (n--) {
char op[2];
int x;
cin >> op >> x;
if (op[0] == 'I') {
insert(x);
} else {
if (find(x)) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
}
return 0;
}
题解2
开放寻址法 : 一般开一个2-3倍的N,然后通过模N算出对应的k ,将其放入数组中,如果遇到相同的k,那么就往后放,直到找到空位置即可
代码2
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 200003; //取大于1e5的第一个质数
const int null = 0x3f3f3f3f; //初始化空值
int h[N]; //开一个2-3倍的N的数组
int find(int x) {
int k = (x % N + N) % N;
while (h[k] != null && h[k] != x) {
k++;
//如果搜索到最后,再从0开始循环
if (k == N) k = 0;
}
return k;
}
int main() {
memset(h, 0x3f, sizeof h);
int n;
cin >> n;
while (n--) {
char op[2];
int x;
cin >> op >> x;
int k = find(x);
if (op[0] == 'I') {
h[k] = x;
} else {
if (h[k] != null) {
cout << "Yes" << endl;
} else {
cout << "No" << endl;
}
}
}
return 0;
}