两种方法,一种拉链法一种开放寻址法
拉链法涉及到单链表的运用,可以看我之前单链表的那篇文章:
java-单链表-数组模拟实现
题目
维护一个集合,支持如下几种操作:
I x,插入一个数 x;
Q x,询问数 x 是否在集合中出现过;
现在要进行 N 次操作,对于每个询问操作输出对应的结果
输入:
5
I 1
I 2
I 3
Q 2
Q 5
输出:
Yes
No
拉链法
public class 哈希表_模拟散列表 {
//初始化,这里的哈希表用的是拉链法,每个hash槽位中镶嵌一个链表储存相同hash值的数据
//注意,N最好取用比数据量大的最小质数,这样可以尽量避免hash值重复,具体可以自己去查,涉及一些数学知识,就不深讲了
public static int N = 100003, index = 0;
public static int[] hash = new int[N], e = new int[N], ne = new int[N];
public static void main(String[] args) {
//初始化,记得将hash数组全部设置为-1,这样才能符合链表的规则
Scanner in = new Scanner(System.in);
int n = Integer.parseInt(in.nextLine());
Arrays.fill(hash, -1);
//操作部分,插入和查找,比较简单就不多说了
while (n-- > 0) {
String[] data_arr = in.nextLine().split(" ");
String model = data_arr[0];
int x = Integer.parseInt(data_arr[1]);
if (model.equals("I")) {
insert(x);
}
else if (model.equals("Q")) {
if (search(x)) {System.out.println("Yes");}
else {System.out.println("No");}
}
}
}
//插入操作,和单链表很像,区别在于head我们使用的是hash[k]的值,而不是自己定义的head
public static void insert(int x) {
//注意,在java和c中,负数进行%,结果会是负数,所以我们这里的操作就是让%的结果变为正数,类似绝对值
int k = (x % N + N) % N;
e[index] = x;
ne[index] = hash[k];
hash[k] = index++;
}
//查找操作,和单链表一致,head被替换为hash[k]
public static boolean search(int x) {
int k = (x % N + N) % N;
for (int i = hash[k]; i!=-1; i = ne[i]) {
if (e[i] == x) {
return true;
}
}
return false;
}
}
开放寻址法
public class 哈希表_开放寻址法 {
//初始化,这里记得一点,使用开放寻址法的话,N要开到数据量的2-3倍左右才行
public static int N = 200003;
public static int[] hash = new int[N];
public static void main(String[] args) {
//初始化,hash数组初始全部为-1
Scanner in = new Scanner(System.in);
int n = Integer.parseInt(in.nextLine());
Arrays.fill(hash, -1);
while(n-- > 0) {
//初始化
String[] data_arr = in.nextLine().split(" ");
String model = data_arr[0];
int x = Integer.parseInt(data_arr[1]);
//因为插入和查找都需要拿到x在hash数组中的位置,就先定义出来
int hash_index = get_hash_index(x);
if (model.equals("I")) {hash[hash_index] = x;}
else if (model.equals("Q")) {
if (hash[hash_index] == x) {System.out.println("Yes");}
else {System.out.println("No");}
}
}
}
//hash index拿到的是x在hash数组中的位置
public static int get_hash_index(int x) {
//这里还是一样,拿到x的正hash值
int k = (x % N + N) % N;
//如果当前k存在值且不等于x,k就继续往后找
while (hash[k]!=-1 && hash[k]!=x) {
k++;
//这里设置限制,如果k等于N了,那么hash值就应该从头开始用
if (k==N) {k=0;}
}
return k;
}
}
声明:算法思路来源为y总,详细请见https://www.acwing.com/
本文仅用作学习记录和交流