哈希->> 两种方法实现
第一次学哈希,下面是这道题的简单介绍
第一种方法:拉链法
简单思路:
- 将大范围的数字映射成[1,N-1]区间的一个数
- 映射的数字记为k,由于可能有多个数映射的结果为k,所以将所有映射值为k的数存在链表里
- 将数组所有数初始化为-1 ( 打标记 )
- 查找一个数a,h=hash(a).我们遍历a的链表就行
- 具体看代码
- N取最小的大于等于数据范围的质数
#include <bits/stdc++.h>
using namespace std;
const int N=100003;
int h[N],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++;
}
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 1;
return 0;
}
int tt;
int main()
{
cin>>tt;
memset(h,-1,sizeof(h));
while(tt--)
{
int x;
char op[2];
scanf("%s",op);
cin>>x;
if(*op=='I')
{
insert(x);
}
else
{
if(find(x))
cout<<"Yes\n";
else
cout<<"No\n";
}
}
}
第二种方法:开放寻址法
简单思路
-
定义
null=0x3f3f3f3f
为无穷大。(null>1e9
) -
数组开到最小的比数据范围的两倍大的质数,并将所有的数初始化为
null
-
关键在于
find
函数:函数中的
t
表示该数字映射的值,随后根据 Y氏蹲坑定理,如果h[t]
中有人,则看下一个坑位,否则就入坑
注意:
方法二中不会死循环因为数组开的足够大,
#include <bits/stdc++.h>
using namespace std;
const int N=200003,null=0x3f3f3f3f;
int h[N];
int find(int x)
{
int t=(x%N+N)%N;
while(h[t]!=null && h[t]!=x)
{
t++;
if(t==N) t=0;
}
return t;
}
int main()
{
memset(h,null,sizeof(h));
int tt;
cin>>tt;
while(tt--)
{
char op[2];int x;
scanf("%s%d",op,&x);
if(op[0]=='I')
{
h[find(x)]=x;
}
else
{
if(h[find(x)]==null)puts("No");
else
puts("Yes");
}
}
}