英文原文
Design a HashMap without using any built-in hash table libraries.
Implement the MyHashMap
class:
MyHashMap()
initializes the object with an empty map.void put(int key, int value)
inserts a(key, value)
pair into the HashMap. If thekey
already exists in the map, update the correspondingvalue
.int get(int key)
returns thevalue
to which the specifiedkey
is mapped, or-1
if this map contains no mapping for thekey
.void remove(key)
removes thekey
and its correspondingvalue
if the map contains the mapping for thekey
.
Example 1:
Input ["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"] [[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]] Output [null, null, null, 1, -1, null, 1, null, -1] Explanation MyHashMap myHashMap = new MyHashMap(); myHashMap.put(1, 1); // The map is now [[1,1]] myHashMap.put(2, 2); // The map is now [[1,1], [2,2]] myHashMap.get(1); // return 1, The map is now [[1,1], [2,2]] myHashMap.get(3); // return -1 (i.e., not found), The map is now [[1,1], [2,2]] myHashMap.put(2, 1); // The map is now [[1,1], [2,1]] (i.e., update the existing value) myHashMap.get(2); // return 1, The map is now [[1,1], [2,1]] myHashMap.remove(2); // remove the mapping for 2, The map is now [[1,1]] myHashMap.get(2); // return -1 (i.e., not found), The map is now [[1,1]]
Constraints:
0 <= key, value <= 106
- At most
104
calls will be made toput
,get
, andremove
.
中文题目
不使用任何内建的哈希表库设计一个哈希映射(HashMap)。
实现 MyHashMap
类:
MyHashMap()
用空映射初始化对象void put(int key, int value)
向 HashMap 插入一个键值对(key, value)
。如果key
已经存在于映射中,则更新其对应的值value
。int get(int key)
返回特定的key
所映射的value
;如果映射中不包含key
的映射,返回-1
。void remove(key)
如果映射中存在key
的映射,则移除key
和它所对应的value
。
示例:
输入: ["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"] [[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]] 输出: [null, null, null, 1, -1, null, 1, null, -1] 解释: MyHashMap myHashMap = new MyHashMap(); myHashMap.put(1, 1); // myHashMap 现在为 [[1,1]] myHashMap.put(2, 2); // myHashMap 现在为 [[1,1], [2,2]] myHashMap.get(1); // 返回 1 ,myHashMap 现在为 [[1,1], [2,2]] myHashMap.get(3); // 返回 -1(未找到),myHashMap 现在为 [[1,1], [2,2]] myHashMap.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]](更新已有的值) myHashMap.get(2); // 返回 1 ,myHashMap 现在为 [[1,1], [2,1]] myHashMap.remove(2); // 删除键为 2 的数据,myHashMap 现在为 [[1,1]] myHashMap.get(2); // 返回 -1(未找到),myHashMap 现在为 [[1,1]]
提示:
0 <= key, value <= 106
- 最多调用
104
次put
、get
和remove
方法
进阶:你能否不使用内置的 HashMap 库解决此问题?
通过代码
高赞题解
🧠 解题思路
本题考查我们对于实现哈希表,有哪些方法,分别有什么利弊?
实现哈希表的原理,其实我们会遇到一个抉择,那就是时间和空间的取舍。
实现方式有两种:
- 超大数组:不考虑空间复杂度,创建超大数组,每个数都能单独存入,且不会位置冲突。
- 链地址法:空间/时间的最佳实践,基于数组实现,并且通过一个 $hash$ 函数生成一个对应的索引,当多个数索引一致的时候,再处理冲突问题,一般我们使用链地址法解决冲突。
🎨 图解演示
<,,>
🍭 示例代码
var MyHashMap = function() {
this.base = 1000;
this.data = new Array(this.base).fill(0).map(i => new Array());
};
MyHashMap.prototype.put = function(key, value) {
let hash = key % this.base;
for(let i of this.data[hash]){
if(i[0] === key) return i[1] = value;
}
this.data[hash].push([key, value]);
};
MyHashMap.prototype.get = function(key) {
let hash = key % this.base;
for(let i of this.data[hash]){
if(i[0] === key) return i[1];
}
return -1;
};
MyHashMap.prototype.remove = function(key) {
let hash = key % this.base;
for(let i of this.data[hash]){
if(i[0] === key) {
let index = this.data[hash].indexOf(i);
this.data[hash].splice(index, 1);
}
}
};
class MyHashMap {
private:
vector<list<pair<int, int>>> data;
static const int base = 769;
static int hash(int key) {
return key % base;
}
public:
MyHashMap(): data(base) {}
void put(int key, int value) {
int h = hash(key);
for (auto it = data[h].begin(); it != data[h].end(); it++) {
if ((*it).first == key) {
(*it).second = value;
return;
}
}
data[h].push_back(make_pair(key, value));
}
int get(int key) {
int h = hash(key);
for (auto it = data[h].begin(); it != data[h].end(); it++) {
if ((*it).first == key) {
return (*it).second;
}
}
return -1;
}
void remove(int key) {
int h = hash(key);
for (auto it = data[h].begin(); it != data[h].end(); it++) {
if ((*it).first == key) {
data[h].erase(it);
return;
}
}
}
};
class MyHashMap {
private class Pair {
private int key;
private int value;
public Pair(int key, int value) {
this.key = key;
this.value = value;
}
public int getKey() {
return key;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
private static final int BASE = 769;
private LinkedList[] data;
public MyHashMap() {
data = new LinkedList[BASE];
for (int i = 0; i < BASE; ++i) {
data[i] = new LinkedList<Pair>();
}
}
public void put(int key, int value) {
int h = hash(key);
Iterator<Pair> iterator = data[h].iterator();
while (iterator.hasNext()) {
Pair pair = iterator.next();
if (pair.getKey() == key) {
pair.setValue(value);
return;
}
}
data[h].offerLast(new Pair(key, value));
}
public int get(int key) {
int h = hash(key);
Iterator<Pair> iterator = data[h].iterator();
while (iterator.hasNext()) {
Pair pair = iterator.next();
if (pair.getKey() == key) {
return pair.value;
}
}
return -1;
}
public void remove(int key) {
int h = hash(key);
Iterator<Pair> iterator = data[h].iterator();
while (iterator.hasNext()) {
Pair pair = iterator.next();
if (pair.key == key) {
data[h].remove(pair);
return;
}
}
}
private static int hash(int key) {
return key % BASE;
}
}
const base = 769
type entry struct {
key, value int
}
type MyHashMap struct {
data []list.List
}
func Constructor() MyHashMap {
return MyHashMap{make([]list.List, base)}
}
func (m *MyHashMap) hash(key int) int {
return key % base
}
func (m *MyHashMap) Put(key, value int) {
h := m.hash(key)
for e := m.data[h].Front(); e != nil; e = e.Next() {
if et := e.Value.(entry); et.key == key {
e.Value = entry{key, value}
return
}
}
m.data[h].PushBack(entry{key, value})
}
func (m *MyHashMap) Get(key int) int {
h := m.hash(key)
for e := m.data[h].Front(); e != nil; e = e.Next() {
if et := e.Value.(entry); et.key == key {
return et.value
}
}
return -1
}
func (m *MyHashMap) Remove(key int) {
h := m.hash(key)
for e := m.data[h].Front(); e != nil; e = e.Next() {
if e.Value.(entry).key == key {
m.data[h].Remove(e)
}
}
}
struct List {
int key;
int val;
struct List* next;
};
void listPush(struct List* head, int key, int val) {
struct List* tmp = malloc(sizeof(struct List));
tmp->key = key;
tmp->val = val;
tmp->next = head->next;
head->next = tmp;
}
void listDelete(struct List* head, int key) {
for (struct List* it = head; it->next; it = it->next) {
if (it->next->key == key) {
struct List* tmp = it->next;
it->next = tmp->next;
free(tmp);
break;
}
}
}
struct List* listFind(struct List* head, int key) {
for (struct List* it = head; it->next; it = it->next) {
if (it->next->key == key) {
return it->next;
}
}
return NULL;
}
void listFree(struct List* head) {
while (head->next) {
struct List* tmp = head->next;
head->next = tmp->next;
free(tmp);
}
}
const int base = 769;
int hash(int key) {
return key % base;
}
typedef struct {
struct List* data;
} MyHashMap;
MyHashMap* myHashMapCreate() {
MyHashMap* ret = malloc(sizeof(MyHashMap));
ret->data = malloc(sizeof(struct List) * base);
for (int i = 0; i < base; i++) {
ret->data[i].key = 0;
ret->data[i].val = 0;
ret->data[i].next = NULL;
}
return ret;
}
void myHashMapPut(MyHashMap* obj, int key, int value) {
int h = hash(key);
struct List* rec = listFind(&(obj->data[h]), key);
if (rec == NULL) {
listPush(&(obj->data[h]), key, value);
} else {
rec->val = value;
}
}
int myHashMapGet(MyHashMap* obj, int key) {
int h = hash(key);
struct List* rec = listFind(&(obj->data[h]), key);
if (rec == NULL) {
return -1;
} else {
return rec->val;
}
}
void myHashMapRemove(MyHashMap* obj, int key) {
int h = hash(key);
listDelete(&(obj->data[h]), key);
}
void myHashMapFree(MyHashMap* obj) {
for (int i = 0; i < base; i++) {
listFree(&(obj->data[i]));
}
free(obj->data);
}
转身挥手
嘿,少年,做图不易,留下个赞或评论再走吧!谢啦~ 💐
差点忘了,祝你牛年大吉 🐮 ,AC 和 Offer 📑 多多益善~
⛲⛲⛲ 期待下次再见~
统计信息
通过次数 | 提交次数 | AC比率 |
---|---|---|
62371 | 97002 | 64.3% |
提交历史
提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
---|
相似题目
题目 | 难度 |
---|---|
设计哈希集合 | 简单 |