Problem-solving patterns with hash maps
Frequency counting, complement lookup and grouping by key — three patterns that cover most map questions.
Most "make this faster" answers reduce to one of three uses of a hash map.
1. Frequency counting
function counts(items) {
const seen = new Map();
for (const item of items) seen.set(item, (seen.get(item) ?? 0) + 1);
return seen;
}
Anagram checks, "first non-repeating character", "top k frequent", "majority element" — all frequency maps. Combine with a heap or bucket sort for the top-k variants.
2. Complement lookup — remember what you have seen
The famous two-sum, in one pass:
function twoSum(items, target) {
const seen = new Map(); // value → index
for (let i = 0; i < items.length; i++) {
const need = target - items[i];
if (seen.has(need)) return [seen.get(need), i];
seen.set(items[i], i);
}
return null;
}
O(n) instead of O(n²), and unlike the two-pointer version it needs no sorting, so it returns original indices.
The generalisation is the prefix-sum map from chapter 3: as you scan, ask "have I already seen the thing that would complete an answer here?"
3. Grouping by a derived key
The trick is choosing a key that makes equivalent things collide on purpose:
function groupAnagrams(words) {
const groups = new Map();
for (const word of words) {
const key = [...word].sort().join(''); // anagrams share this key
if (!groups.has(key)) groups.set(key, []);
groups.get(key).push(word);
}
return [...groups.values()];
}
Other useful derived keys: row - col and row + col for chessboard diagonals, a normalised shape for isomorphic strings, a sorted tuple for equivalent sets.
Choosing the right map in JavaScript
| Need | Use |
|---|---|
| Any key type, size, insertion order | Map |
| Membership only | Set |
| String keys, JSON-friendly | plain object |
| Keys that should not prevent garbage collection | WeakMap |
Prefer Map over an object for dynamic keys: no prototype surprises with keys like __proto__ or constructor, and size is O(1).
The cost you are accepting
Every one of these buys time with O(n) memory. Say so when you present the solution — "O(n) time, O(n) space, trading memory for the second pass" is the complete sentence.