加载中...
706-设计哈希映射(Design HashMap)
发表于:2021-12-03 | 分类: 简单
字数统计: 589 | 阅读时长: 3分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/design-hashmap

英文原文

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 the key already exists in the map, update the corresponding value.
  • int get(int key) returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key.
  • void remove(key) removes the key and its corresponding value if the map contains the mapping for the key.

 

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 to put, get, and remove.

中文题目

不使用任何内建的哈希表库设计一个哈希映射(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
  • 最多调用 104putgetremove 方法

 

进阶:你能否不使用内置的 HashMap 库解决此问题?

通过代码

高赞题解

图解每日一练.jpg


🧠 解题思路

本题考查我们对于实现哈希表,有哪些方法,分别有什么利弊?

实现哈希表的原理,其实我们会遇到一个抉择,那就是时间和空间的取舍。

实现方式有两种:

  1. 超大数组:不考虑空间复杂度,创建超大数组,每个数都能单独存入,且不会位置冲突。
  2. 链地址法:空间/时间的最佳实践,基于数组实现,并且通过一个 $hash$ 函数生成一个对应的索引,当多个数索引一致的时候,再处理冲突问题,一般我们使用链地址法解决冲突。

🎨 图解演示

<1.jpg,2.jpg,3.jpg>


🍭 示例代码

[]
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%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
设计哈希集合 简单
上一篇:
705-设计哈希集合(Design HashSet)
下一篇:
802-找到最终的安全状态(Find Eventual Safe States)
本文目录
本文目录