← All patterns
Hash Maps
Constant-time keyed lookup. Frequency counting, complement search, anagram grouping, two-sum, and running aggregations keyed by computed signatures — the most reused primitive in the entire toolkit.
29 problems
13 Easy 13 Medium 3 Hard
Constant-time keyed lookup is the most-reused primitive in DSA. Use hash maps for frequency counting, complement search (two-sum), grouping by signature (anagrams via sorted-string key), and rolling state by computed key (prefix-sum, modular hash).
The design question is the *key* — picking a canonical form so that 'same logical thing' hashes equally is the whole game.
When to reach for this pattern
- Look up 'have I seen this value before?'
- Group items by a derived property (anagram, signature)
- Count occurrences and act on the count
- Two-sum-like complement searches
Canonical template
// complement search
unordered_map<int, int> seen;
for (int i = 0; i < (int)nums.size(); ++i) {
int need = target - nums[i];
if (auto it = seen.find(need); it != seen.end())
return {it->second, i};
seen[nums[i]] = i;
}
// group anagrams by sorted-string key
unordered_map<string, vector<string>> groups;
for (auto& s : strs) {
string key = s;
sort(key.begin(), key.end());
groups[key].push_back(s);
} C++ · adapt the names and types to your problem.
Common pitfalls
- Order of insertion vs lookup matters — inserting first means using a value to find itself
- Hash collisions on adversarial inputs degrade to O(n) — competitive code may need salted maps
- Choosing a poor key (non-canonical) groups distinct things or splits identical things
-
unordered_map<>iteration order is implementation-defined — don't rely on it
Related patterns
Problems (29)
- Easy
- Medium
- Easy
- Easy
- Easy
- Medium
- Easy
- Medium
- Easy
- Easy
- Medium
- Medium
- Medium
- Medium
- Hard
- Medium
- Hard
- Hard
- Easy
- Easy
- Medium
- Easy
- Medium
- Easy
- Medium
- Easy
- Medium
- Medium
- Easy