1. 题目描述
不使用任何内建的哈希表库设计一个哈希集合(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 ,(已移除)
提示:
0 <= key <= 106
- 最多调用
104
次add
、remove
和contains
2. 解答
2.1 数组法
var MyHashSet = function() {
this.myHashSet = [];
};
MyHashSet.prototype.add = function(key) {
this.myHashSet[key] = key;
};
MyHashSet.prototype.remove = function(key) {
this.myHashSet[key] = null;
};
MyHashSet.prototype.contains = function(key) {
return !!this.myHashSet[key]; // 有值的两次取反后都为true
};
2.1 链地址法
我们开辟一个大小为limit
的数组,数组的每个位置是一个链表bucket
。当计算出哈希值hashCode
之后,就插入到对应位置的链表当中。(根据注释掉的部分更容易理解)
/**
* Initialize your data structure here.
*/
var MyHashSet = function() {
// 创建的哈希表需要
// 有一个数组存放数据
// 有内存限制
// 有长度记录
this.myHash = []; // 存放元素的数组
this.limit = 769; // 最好为质数
//this.myHash = new Array(this.limit).fill(0).map(() => new Array());
this.count = 0; // 表示当前已经存在了多少数据
// 哈希函数
// 将需要存入的数据转换为一个较大的数
MyHashSet.prototype.hashfunc = function(key){
// var hashCode = 0;
// for(var i = 0; i < str.length; i++){
// hashCode = 37 * hashCode + str.charCodeAt(i);
// }
// var index = hashCode % this.limit;
// return index;
return key % this.limit;
}
};
/**
* @param {number} key
* @return {void}
*/
MyHashSet.prototype.add = function(key) {
// 1. 通过传来的key获取hashCode,查找到对应的元素
var index = this.hashfunc(key);
// 2. 根据index取出对应的bucket
var bucket = this.myHash[index];
//判断bucket是否为空
if(bucket == null){
bucket = [];
this.myHash[index] = bucket;
}
// // 判断要添加的数是否已存在
// for(let i = 0; i < bucket.length; i++){
// if(key == bucket[i]){
// return;
// }
// }
for(const element of bucket){
if(element == key) return;
}
bucket.push(key);
this.count++;
};
/**
* @param {number} key
* @return {void}
*/
MyHashSet.prototype.remove = function(key) {
var index = this.hashfunc(key);
var bucket = this.myHash[index];
if(bucket == null) return false;
for(let i = 0; i < bucket.length; i++){
if(key == bucket[i]){
bucket.splice(i,1);
this.count--;
return;
}
}
};
/**
* Returns true if this set contains the specified element
* @param {number} key
* @return {boolean}
*/
MyHashSet.prototype.contains = function(key) {
var index = this.hashfunc(key);
var bucket = this.myHash[index];
if(bucket == null) return false;
// for(let i = 0; i < bucket.length; i++){
// if(key == bucket[i]){
// return true;
// }
// }
for(const element of bucket){
if(element == key){
return true;
}
}
return false;
};