我们一般对于HashSet和HashMap都是直接使用数据结构,具体让自己实现一个HashSet和HashMap,又该怎样实现呢?
文章目录
1. 设计哈希集合
1.1 题目描述
题目链接:705. 设计哈希集合
1.2 思路分析
(1)简单数组
由于题目给出了 0 <= key <= 10^6 数据范围,同时限定了 key 只能是 int。
我们可以直接使用一个 boolean 数组记录某个 key 是否存在,key 直接对应 boolean 的下标。
Java代码实现:
class MyHashSet {
// 数组实现
boolean[] node = new boolean[1000009];
public MyHashSet() {
}
public void add(int key) {
node[key] = true;
}
public void remove(int key) {
node[key] = false;
}
public boolean contains(int key) {
return node[key];
}
}
/**
* Your MyHashSet object will be instantiated and called as such:
* MyHashSet obj = new MyHashSet();
* obj.add(key);
* obj.remove(key);
* boolean param_3 = obj.contains(key);
*/
(2)链表解法
利用「链表」来构建 Set,这也是工程上最简单的一种实现方式。
class MyHashSet {
// 链表实现Set
Node[] nodes = new Node[10009];
static class Node {
private int key;
private Node next;
private Node(int key) {
this.key = key;
}
}
int getIndex(int key) {
// 因为 nodes 的长度只有 10009,对应的十进制的 10011100011001(总长度为 32 位,其余高位都是 0)
// 为了让 key 对应的 hash 高位也参与运算,这里对 hashCode 进行右移异或
// 使得 hashCode 的高位随机性和低位随机性都能体现在低 16 位中
int hash = Integer.hashCode(key);
hash ^= (hash >>> 16);
return hash % nodes.length;
}
public MyHashSet() {
}
public void add(int key) {
// 根据 key 获取哈希桶的位置
int idx = getIndex(key);
// 判断链表中是否已经存在
Node loc = nodes[idx], tmp = loc;
if (loc != null) {
Node prev = null;
while (tmp != null) {
if (tmp.key == key) {
return;
}
prev = tmp;
tmp = tmp.next;
}
tmp = prev;
}
Node node = new Node(key);
// 尾插法
if (tmp != null) {
tmp.next