题目描述
不使用任何内建的哈希表库设计一个哈希集合(HashSet)
。
实现 MyHashSet
类:
void add(key)
向哈希集合中插入值key
。
bool contains(key)
返回哈希集合中是否存在这个值key
。
void remove(key)
将给定值key
从哈希集合中删除。如果哈希集合中没有这个值,什么也不做。
样例
输入:
["MyHashSet", "add", "add", "contains", "contains", "add", "contains", "remove", "contains"]
[[], [1], [2], [1], [3], [2], [2], [2], [2]]
输出:
[null, null, null, true, false, null, true, null, false]
解释:
MyHashSet myHashSet = new MyHashSet();
myHashSet.add(1); // set = [1]
myHashSet.add(2); // set = [1, 2]
myHashSet.contains(1); // 返回 True
myHashSet.contains(3); // 返回 False ,(未找到)
myHashSet.add(2); // set = [1, 2]
myHashSet.contains(2); // 返回 True
myHashSet.remove(2); // set = [1]
myHashSet.contains(2); // 返回 False ,(已移除)
算法1
(数组法)
- 即规定一个够大的数组,插入讲该数组值赋值为1
- 删除即赋值为0
- 检查存在不存在即检查是1还是0
时间复杂度
O(1)的操作复杂度,但是该方法较为浪费空间
C++ 代码
class MyHashSet {
public:
const int N = 1e6;
vector<int> res;
/** Initialize your data structure here. */
MyHashSet() {
res.resize(N);
}
void add(int key) {
res[key] = 1;
}
void remove(int key) {
res[key] = 0;
}
/** Returns true if this set contains the specified element */
bool contains(int key) {
return res[key] == 1;
}
};
/**
* Your MyHashSet object will be instantiated and called as such:
* MyHashSet* obj = new MyHashSet();
* obj->add(key);
* obj->remove(key);
* bool param_3 = obj->contains(key);
*/
算法2
(开链法)
即采用真正哈希表的思路:
- 通过哈希函数获取索引
- 当发生索引冲突(哈希冲突)采用开链法,即在每个节点下放置链表
- 插入的时候检查有无冲突,没冲突构建新的链表,有冲突则在链表寻找有无当前元素,有则直接返回,没有则添加到最后面
- 删除的时候则在链表中遍历寻找该元素节点进行删除
- exist的思路即是在链表中检查该节点是否存在
时间复杂度
基本与链表的操作时间复杂度相同,但是更加节省线性空间
参考文献
C++ 代码
class MyHashSet {
public:
/** Initialize your data structure here. */
MyHashSet() {
key_size = 1e5;
hashArray = vector<ListNode*>(key_size);
}
int to_hash(int key) {
return key % key_size;
}
void add(int key) {
int idx = to_hash(key);
if(!hashArray[idx]) hashArray[idx] = new ListNode(key);
else{
ListNode* p = hashArray[idx];
while(p){
if(p->val == key) return;
p = p->next;
}
p = new ListNode(key);
}
}
void remove(int key) {
int idx = to_hash(key);
if(!hashArray[idx]) return;
if(hashArray[idx]->val == key) hashArray[idx] = hashArray[idx]->next;
else {
ListNode* pre = hashArray[idx];
ListNode* p = pre->next;
while(p) {
if(p->val == key) {
pre->next = p->next;
return;
}
pre = p;
p = p->next;
}
}
}
/** Returns true if this set contains the specified element */
bool contains(int key) {
int idx = to_hash(key);
ListNode* p = hashArray[idx];
while(p) {
if(p->val == key) return true;
p = p->next;
}
return false;
}
private:
vector<ListNode*> hashArray;
int key_size;
};
/**
* Your MyHashSet object will be instantiated and called as such:
* MyHashSet* obj = new MyHashSet();
* obj->add(key);
* obj->remove(key);
* bool param_3 = obj->contains(key);
*/
**