HashMap Implementation from Scratch in DSA Javascript - Time & Space Complexity
When building a HashMap from scratch, it's important to know how fast it can add, find, or remove items.
We want to understand how the time to do these actions changes as the number of stored items grows.
Analyze the time complexity of the following simple HashMap methods.
class SimpleHashMap {
constructor(size) {
this.buckets = new Array(size).fill(null).map(() => []);
}
_hash(key) {
let hash = 0;
for (let char of key) {
hash += char.charCodeAt(0);
}
return hash % this.buckets.length;
}
set(key, value) {
const index = this._hash(key);
const bucket = this.buckets[index];
for (let i = 0; i < bucket.length; i++) {
if (bucket[i][0] === key) {
bucket[i][1] = value;
return;
}
}
bucket.push([key, value]);
}
get(key) {
const index = this._hash(key);
const bucket = this.buckets[index];
for (let [k, v] of bucket) {
if (k === key) return v;
}
return undefined;
}
}
This code creates a simple HashMap with buckets as arrays and handles collisions by storing key-value pairs in each bucket.
Look at the loops and repeated steps in the code.
- Primary operation: Looping through a bucket array to find a key.
- How many times: Depends on the number of items in that bucket, which varies with total items and bucket count.
As more items are added, buckets may hold more pairs, making searches longer.
| Input Size (n) | Approx. Operations per get/set |
|---|---|
| 10 | About 1 to 2 checks (if buckets are 5) |
| 100 | About 10 to 20 checks (if buckets are 10) |
| 1000 | About 50 to 100 checks (if buckets are 20) |
Pattern observation: More items mean longer bucket lists, so operations grow roughly in proportion to items per bucket.
Time Complexity: O(n / b) where n is items and b is bucket count.
This means the time depends on how many items share the same bucket; more buckets mean faster operations.
[X] Wrong: "HashMap operations always take constant time no matter what."
[OK] Correct: If many keys end up in the same bucket, searching that bucket takes longer, so time grows with items per bucket.
Understanding how collisions affect speed shows you know the real workings of HashMaps, a key skill for coding interviews.
"What if we increased the number of buckets as items grow? How would that change the time complexity?"
Practice
HashMap in data structures?Solution
Step 1: Understand what a HashMap stores
A HashMap stores data as key-value pairs, allowing quick access to values using keys.Step 2: Compare with other data structures
Unlike lists or stacks, HashMaps focus on fast lookup, not order or sequence.Final Answer:
To store key-value pairs for fast data retrieval -> Option DQuick Check:
HashMap = key-value fast access [OK]
- Confusing HashMap with list or stack
- Thinking HashMap stores data in order
- Assuming HashMap stores only values without keys
Solution
Step 1: Check class syntax and property initialization
class HashMap { constructor() { this.map = {}; } } correctly defines a class with a constructor initializing an object propertythis.map.Step 2: Identify errors in other options
class HashMap { constructor() { map = []; } } missesthis., somapis not a property. function HashMap() { this.map = new Map(); } uses function syntax, not class. class HashMap { constructor() { this.map = null; } } initializesthis.mapto null, which is not useful for storing pairs.Final Answer:
class HashMap { constructor() { this.map = {}; } } -> Option AQuick Check:
Proper class constructor uses this.property = value [OK]
- Forgetting 'this.' before property name
- Mixing function and class syntax
- Initializing property to null instead of object
class HashMap {
constructor() {
this.map = {};
}
set(key, value) {
this.map[key] = value;
}
get(key) {
return this.map[key] || null;
}
}
const h = new HashMap();
h.set('a', 1);
h.set('b', 2);
h.set('a', 3);
console.log(h.get('a'));
What will be printed?Solution
Step 1: Trace the set operations
First, key 'a' is set to 1, then 'b' to 2, then 'a' is updated to 3, overwriting previous value.Step 2: Check the get operation
Callingget('a')returns the current value for 'a', which is 3.Final Answer:
3 -> Option AQuick Check:
Last set value for 'a' = 3 [OK]
- Assuming first set value remains
- Confusing keys and values
- Expecting null if key was set before
remove(key) {
delete this.map.key;
}
What is the correct fix?Solution
Step 1: Understand property access in JavaScript objects
Using dot notation withthis.map.keylooks for property literally named 'key', not the variable key.Step 2: Use bracket notation for dynamic keys
Bracket notationthis.map[key]accesses the property named by the variablekey. Sodelete this.map[key];correctly deletes the key-value pair.Final Answer:
Change to delete this.map[key]; -> Option CQuick Check:
Use brackets for variable keys [OK]
- Using dot notation with variable keys
- Using non-existent methods like remove()
- Using wrong delete syntax
keys() method in your HashMap class that returns all keys stored. Which of these implementations correctly returns an array of keys?Solution
Step 1: Identify how to get keys from a plain object
JavaScript'sObject.keys()returns an array of keys from an object.Step 2: Check other options for correctness
keys() { return this.map.keys(); } assumesthis.mapis a Map object, but here it's a plain object, sothis.map.keys()is undefined. keys() { return Object.values(this.map); } returns values, not keys. keys() { return this.map.getKeys(); } uses a non-existent method.Final Answer:
keys() { return Object.keys(this.map); } -> Option BQuick Check:
Object.keys() returns keys array [OK]
- Using Map methods on plain objects
- Returning values instead of keys
- Calling non-existent methods
Ready to prove it?
Pass the test and this pattern moves unknown
