目录
一、题目
1、题目
题目链接{点击跳转}
二、思路
1、知识点
将任意一个对象传进来或者任何一个数据传进来,然后映射到一个位置int下标index
eg、 String
哈希碰撞
↑拉链法
时间复杂度
几乎O(1) 除非做的很差or size
太小了 导致O(n)
应用
:把较大的数据映射到较小的数
2、拉链法
①、插入操作
类似与单链表插入 没做过可以看下 单链表
第一步:创建一个点e[idx] = x
第二步 创建指针 ne[idx] = h[k]
第三步:修改指针h[k] = idx++
②、查询操作
![在这里插入
3、开放寻址法
①0x3f3f3f3f
的作用:
1 、相当于无穷大
2、不容易溢出
3、方便数组赋值 memset(a,0x3f,sizeof(a))
参考 – 大佬的链接
②思路
三、AC代码
拉链法
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100003;//+3是为了让n变为质数 减少冲突的概率
int h[N],e[N],ne[N],idx;
//插入 :头插法
void insert (int x) {
//c++ 负数取模结果还是负数
// 根据取值范围 x % N + N必是正数
//不加(x + N)% N是因为 x可能取值是负数 根据取值范围 加上N可能还是负数
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 true;
}
}
return false;
}
int main () {
int n;
cin >> n;
memset(h, -1, sizeof h);//清空 空指针用-1表示
while (n --) {
string op;
int x;
cin >> op >> x;
if (op == "I") {
insert(x);
}
else {
if (find(x)) {
puts("Yes");
}
else {
puts("No");
}
}
}
return 0;
}
开放寻址法
#include <iostream>
#include <cstring>
using namespace std;
//开放寻址法一般开 数据范围的 2~3倍
const int N = 200003;//+3是为了让n变为质数 减少冲突的概率
const int null = 0x3f3f3f3f;
// 0x3f3f3f3f的十进制是1061109567,也就是10^9级别的(和0x7fffffff一个数量级),
// 而一般场合下的数据都是小于10^9的,所以它可以作为无穷大使用而不致出现数据大于无穷大的情形。
int h[N];
int find (int x) {
int k = (x % N + N) % N;//映射k的下标
while (h[k] != null && h[k] != x) {
k++;
if (k == N) {//到最后一个位置
k = 0;
}
}
return k;//如果这个位置为空 则返回它的存储位置
}
int main () {
int n;
cin >> n;
memset(h,0x3f, sizeof h);//将数组清空
while (n --) {
string op;
int x;
cin >> op >> x;
if (op == "I") {
h[find(x)] = x;
}
else {
if (h[find(x)] == null) {
puts("No");
}
else {
puts("Yes");
}
}
}
return 0;
}
四、总结
结尾: