Design HashMap
The drill: Build a key-value map from scratch over a bounded range of non-negative integer keys — put, get, and remove — without a language's built-in hash map.
A key-value map needs building from scratch over non-negative integer keys — put a value under a key, get the value stored there, and remove a key — without reaching for a language's built-in hash map.
Putting a value under a key that's already in use simply overwrites whatever was there before; getting a key that was never put, or has since been removed, reports a defined 'not found' signal instead of a real value.
This site drives the drill as a sequence of operations against one live instance, each acting only on the map's current contents at the moment it's called.
- keys are non-negative integers within a bounded, modest range
- put on an existing key overwrites its value
- get on a missing key returns a defined not-found signal, commonly −1
- no built-in hash map type may back the implementation
HINT 1 THE NUDGE
A list of [key, value] pairs gets you correctness immediately, but every get or remove means scanning for the key. What would make finding a key stop depending on how many you've stored?
HINT 2 THE STRUCTURE
Keys live in a bounded range, so hashing them into a fixed number of buckets turns 'which bucket holds this key' into one division. Each bucket only ever holds the keys that collide.
HINT 3 ONE STEP FROM THE ANSWER
Store each bucket as a short list of [key, value] pairs. put replaces an existing pair or appends a new one; get and remove scan only that one bucket instead of the whole map.
Ops run against one live map, each key hashed into a bucket of [key, value] pairs.
class MyHashMap:
def __init__(self):
self.buckets = 1000
self.table = [[] for _ in range(self.buckets)]
def put(self, key: int, value: int) -> None:
bucket = self.table[key % self.buckets]
for pair in bucket:
if pair[0] == key:
pair[1] = value
return
bucket.append([key, value])
def get(self, key: int) -> int:
bucket = self.table[key % self.buckets]
for k, v in bucket:
if k == key:
return v
return -1
def remove(self, key: int) -> None:
bucket = self.table[key % self.buckets]
for i, pair in enumerate(bucket):
if pair[0] == key:
del bucket[i]
returnclass MyHashMap:
def __init__(self):
self.pairs = [] # list of [key, value]
def put(self, key: int, value: int) -> None:
for pair in self.pairs:
if pair[0] == key:
pair[1] = value
return
self.pairs.append([key, value])
def get(self, key: int) -> int:
for k, v in self.pairs:
if k == key:
return v
return -1
def remove(self, key: int) -> None:
for i, pair in enumerate(self.pairs):
if pair[0] == key:
del self.pairs[i]
returnclass MyHashMap {
private final List<int[]>[] table;
private final int buckets = 1000;
public MyHashMap() {
table = new List[buckets];
for (int i = 0; i < buckets; i++) {
table[i] = new ArrayList<>();
}
}
public void put(int key, int value) {
List<int[]> bucket = table[key % buckets];
for (int[] pair : bucket) {
if (pair[0] == key) {
pair[1] = value;
return;
}
}
bucket.add(new int[] { key, value });
}
public int get(int key) {
List<int[]> bucket = table[key % buckets];
for (int[] pair : bucket) {
if (pair[0] == key) {
return pair[1];
}
}
return -1;
}
public void remove(int key) {
List<int[]> bucket = table[key % buckets];
for (int i = 0; i < bucket.size(); i++) {
if (bucket.get(i)[0] == key) {
bucket.remove(i);
return;
}
}
}
}class MyHashMap {
private final List<int[]> pairs = new ArrayList<>();
public MyHashMap() {
}
public void put(int key, int value) {
for (int[] pair : pairs) {
if (pair[0] == key) {
pair[1] = value;
return;
}
}
pairs.add(new int[] { key, value });
}
public int get(int key) {
for (int[] pair : pairs) {
if (pair[0] == key) {
return pair[1];
}
}
return -1;
}
public void remove(int key) {
for (int i = 0; i < pairs.size(); i++) {
if (pairs.get(i)[0] == key) {
pairs.remove(i);
return;
}
}
}
}✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED