Design HashMap
Easy · Linked List · Explanation and code example
Linked List
How it works
To reduce memory usage, we use a hash table with separate chaining. We create an array of buckets (smaller than the key range) and use a hash function (key modulo bucket count) to determine which bucket a key belongs to. Each bucket is a linked list that stores key-value pairs. This handles collisions by chaining multiple entries in the same bucket.
Steps
- Initialize an array of
1000buckets, each containing a dummy head node for a linked list. - Define
hash(key)askey % 1000. - For
put(key, value): Traverse the linked list athash(key). If a node with the matching key exists, update its value. Otherwise, append a new node with the key-value pair. - For
get(key): Traverse the linked list athash(key). If a node with the matching key is found, return its value. Otherwise, return-1. - For
remove(key): Traverse the linked list athash(key). If a node with the matching key is found, remove it by updating the previous node'snextpointer.
Complexity
- Time complexity:
O(frac{n}{k})for each function call. - Space complexity:
O(k + m)
Where
nis the number of keys,kis the size of the map (1000) andmis the number of unique keys.
Things to watch for
Not Updating Existing Keys on Put
When a key already exists, put() should update its value rather than adding a duplicate entry.
Traversing from Dummy Node in Get
When getting a value, start from dummy.next (actual first element), not the dummy head itself.
Python code example
class ListNode:
def __init__(self, key = -1, val = -1, next = None):
self.key = key
self.val = val
self.next = next
class MyHashMap:
def __init__(self):
self.map = [ListNode() for _ in range(1000)]
def hash(self, key: int) -> int:
return key % len(self.map)
def put(self, key: int, value: int) -> None:
cur = self.map[self.hash(key)]
while cur.next:
if cur.next.key == key:
cur.next.val = value
return
cur = cur.next
cur.next = ListNode(key, value)
def get(self, key: int) -> int:
cur = self.map[self.hash(key)].next
while cur:
if cur.key == key:
return cur.val
cur = cur.next
return -1
def remove(self, key: int) -> None:
cur = self.map[self.hash(key)]
while cur.next:
if cur.next.key == key:
cur.next = cur.next.next
return
cur = cur.next
C++ code example
class MyHashMap {
private:
struct ListNode {
int key, val;
ListNode* next;
ListNode(int key = -1, int val = -1, ListNode* next = nullptr)
: key(key), val(val), next(next) {}
};
vector<ListNode*> map;
int hash(int key) {
return key % map.size();
}
public:
MyHashMap() {
map.resize(1000);
for (auto& bucket : map) {
bucket = new ListNode(0);
}
}
void put(int key, int value) {
ListNode* cur = map[hash(key)];
while (cur->next) {
if (cur->next->key == key) {
cur->next->val = value;
return;
}
cur = cur->next;
}
cur->next = new ListNode(key, value);
}
int get(int key) {
ListNode* cur = map[hash(key)]->next;
while (cur) {
if (cur->key == key) {
return cur->val;
}
cur = cur->next;
}
return -1;
}
void remove(int key) {
ListNode* cur = map[hash(key)];
while (cur->next) {
if (cur->next->key == key) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
return;
}
cur = cur->next;
}
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.