Hash Tables & Hash Maps — Internal Working
📖 Concept
A hash table (hash map) is the most important data structure for coding interviews. It provides O(1) average lookup, insert, and delete by mapping keys to array indices using a hash function.
How it works internally:
- Hash function: Converts key → integer index (e.g., "alice" → 42)
- Array of buckets: The index maps to a position in an array
- Collision handling: When two keys hash to the same index
Collision resolution strategies:
- Chaining (most common): Each bucket holds a linked list. Collisions add to the list.
- Open addressing: Find the next empty slot (linear probing, quadratic probing, double hashing)
Load factor = number of elements / number of buckets
- When load factor exceeds threshold (~0.75), the table resizes (double buckets, rehash all)
- This keeps chains short → O(1) average
Complexity:
| Operation | Average | Worst Case |
|---|---|---|
| Insert | O(1) | O(n) (all keys collide) |
| Lookup | O(1) | O(n) |
| Delete | O(1) | O(n) |
JavaScript's Map vs Object:
Map: Any key type, preserves insertion order, has .size, iterableObject: String/Symbol keys only, prototype chain, not iterable by default- For DSA: always prefer
MaporSet
🏠 Real-world analogy: A library catalog. The hash function is like organizing books by the first letter of the author's last name (A → shelf 1, B → shelf 2). If two books start with "S" (collision), they share a shelf (chaining).
💻 Code Example
1// BUILD HASH TABLE FROM SCRATCH2class HashTable {3 constructor(size = 53) {4 this.buckets = new Array(size);5 this.size = size;6 this.count = 0;7 }89 // Simple hash function10 _hash(key) {11 let hash = 0;12 const PRIME = 31; // Prime reduces collisions13 for (let i = 0; i < Math.min(key.length, 100); i++) {14 hash = (hash * PRIME + key.charCodeAt(i)) % this.size;15 }16 return hash;17 }1819 set(key, value) {20 const idx = this._hash(key);21 if (!this.buckets[idx]) this.buckets[idx] = [];22 // Check if key exists (update)23 for (const pair of this.buckets[idx]) {24 if (pair[0] === key) { pair[1] = value; return; }25 }26 this.buckets[idx].push([key, value]);27 this.count++;28 }2930 get(key) {31 const idx = this._hash(key);32 if (!this.buckets[idx]) return undefined;33 for (const pair of this.buckets[idx]) {34 if (pair[0] === key) return pair[1];35 }36 return undefined;37 }3839 delete(key) {40 const idx = this._hash(key);41 if (!this.buckets[idx]) return false;42 const bucket = this.buckets[idx];43 for (let i = 0; i < bucket.length; i++) {44 if (bucket[i][0] === key) {45 bucket.splice(i, 1);46 this.count--;47 return true;48 }49 }50 return false;51 }52}5354// COMMON INTERVIEW PATTERNS WITH HASH MAPS5556// Two Sum — O(n) with hash map57function twoSum(nums: number[], target: number): [number, number] {58 const map = new Map<number, number>();59 for (let i = 0; i < nums.length; i++) {60 const complement = target - nums[i];61 if (map.has(complement)) return [map.get(complement)!, i];62 map.set(nums[i], i);63 }64 throw new Error("No solution");65}6667// Group Anagrams — O(n * k log k)68function groupAnagrams(strs: string[]): string[][] {69 const map = new Map<string, string[]>();70 for (const s of strs) {71 const key = s.split('').sort().join('');72 if (!map.has(key)) map.set(key, []);73 map.get(key)!.push(s);74 }75 return Array.from(map.values());76}7778// Frequency Counter — Universal pattern79function topKFrequent(nums: number[], k: number): number[] {80 const freq = new Map<number, number>();81 for (const n of nums) freq.set(n, (freq.get(n) || 0) + 1);82 return [...freq.entries()]83 .sort((a, b) => b[1] - a[1])84 .slice(0, k)85 .map(e => e[0]);86}8788// Subarray Sum Equals K — Prefix sum + hash map89function subarraySum(nums: number[], k: number): number {90 const prefixCount = new Map<number, number>([[0, 1]]);91 let sum = 0, count = 0;92 for (const num of nums) {93 sum += num;94 if (prefixCount.has(sum - k)) count += prefixCount.get(sum - k)!;95 prefixCount.set(sum, (prefixCount.get(sum) || 0) + 1);96 }97 return count;98}
🏋️ Practice Exercise
Practice Problems (Easy → Hard):
- Build a hash table from scratch with set, get, delete
- Two Sum — find indices of two numbers that add to target
- Check if two strings are anagrams using a hash map
- Find the first non-repeating character in a string
- Group anagrams from an array of strings
- Find the longest consecutive sequence in an unsorted array
- Count subarrays with sum equal to k (prefix sum + hash map)
- Top K frequent elements
- Design a consistent hashing ring (conceptual)
- Implement an LRU Cache using hash map + doubly linked list
⚠️ Common Mistakes
Using Object as a hash map — use Map for non-string keys, better performance, and .size property
Not understanding that hash map O(1) is AVERAGE, not guaranteed — worst case with bad hash is O(n)
Forgetting that Map preserves insertion order in JavaScript — this is guaranteed by the spec
Using JSON.stringify as a hash key — it's slow and order-dependent for objects
Not considering hash collisions in custom implementations — always handle them
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Hash Tables & Hash Maps — Internal Working