This document explains the hash table pattern as used throughout the repository's algorithm solutions. Hash tables (also known as hash maps, dictionaries, or associative arrays) provide constant-time average-case lookups and are fundamental to solving problems involving uniqueness checks, frequency counting, and value-to-index mappings.
For other algorithmic patterns, see:
Hash tables store key-value pairs with $O(1)$ average-case time complexity for insertion, deletion, and lookup operations. The pattern is particularly effective when:
Trade-off: Hash tables use $O(n)$ space complexity, exchanging memory for speed compared to $O(n^2)$ brute-force approaches.
Sources: solution/0000-0099/0001.Two Sum/README.md1-410 lcci/01.02.Check Permutation/README.md1-347 lcci/01.04.Palindrome Permutation/README.md1-298
The canonical hash table problem. Given an array and a target, find two indices where values sum to the target.
Key Insight: Instead of checking all pairs ($O(n^2)$), store each value with its index in a hash table, then check if target - current_value exists.
Sources: solution/0000-0099/0001.Two Sum/README.md67-78 solution/0000-0099/0001.Two Sum/README_EN.md64-74
The pattern is consistent across all supported languages, using each language's native hash table implementation:
| Language | Hash Table Type | Declaration | Lookup | Insert |
|---|---|---|---|---|
| Python | dict | d = {} | y in d | d[x] = i |
| Java | HashMap<K,V> | Map<Integer, Integer> d = new HashMap<>() | d.containsKey(y) | d.put(x, i) |
| C++ | unordered_map<K,V> | unordered_map<int, int> d | d.contains(y) | d[x] = i |
| Go | map[K]V | d := map[int]int{} | j, ok := d[y] | d[x] = i |
| TypeScript | Map<K,V> | const d = new Map<number, number>() | d.has(y) | d.set(x, i) |
| Rust | HashMap<K,V> | let mut d = HashMap::new() | d.get(&y) | d.insert(x, i) |
Implementation Examples:
Sources: solution/0000-0099/0001.Two Sum/Solution.py1-8 solution/0000-0099/0001.Two Sum/Solution.java1-13 solution/0000-0099/0001.Two Sum/Solution.cpp1-14 solution/0000-0099/0001.Two Sum/Solution.go1-11 solution/0000-0099/0001.Two Sum/Solution.ts1-11 solution/0000-0099/0001.Two Sum/Solution.rs1-15
Determine if one string is a permutation (rearrangement) of another by counting character frequencies.
Key Insight: Two strings are permutations if and only if they have identical character frequency distributions.
Sources: lcci/01.02.Check Permutation/README.md40-56 lcci/01.02.Check Permutation/README_EN.md47-63
Character Array Optimization: When the character set is constrained (e.g., lowercase English letters), use an array of size 26 instead of a hash table for better cache performance:
// Java implementation
int[] cnt = new int[26];
for (char c : s1.toCharArray()) {
++cnt[c - 'a']; // Map 'a'→0, 'b'→1, ..., 'z'→25
}
for (char c : s2.toCharArray()) {
if (--cnt[c - 'a'] < 0) {
return false;
}
}
Language-Specific Implementations:
Sources: lcci/01.02.Check Permutation/Solution.java1-17 lcci/01.02.Check Permutation/README.md44-56
Check if a string's characters can be rearranged to form a palindrome.
Key Insight: A string can form a palindrome if and only if at most one character has an odd frequency count.
Sources: lcci/01.04.Palindrome Permutation/README.md36-157 lcci/01.04.Palindrome Permutation/README_EN.md33-156
Python Implementation using Counter:
The expression v & 1 efficiently checks if v is odd using bitwise AND.
Java Implementation:
Sources: lcci/01.04.Palindrome Permutation/Solution.py1-4 lcci/01.04.Palindrome Permutation/Solution.java1-12
This approach optimizes space by only tracking characters with odd counts:
Implementation Comparison:
| Language | Set Type | Add Operation | Remove Operation | Check Size |
|---|---|---|---|---|
| Python | set() | vis.add(c) | vis.remove(c) | len(vis) < 2 |
| Java | HashSet<Character> | !vis.add(c) | vis.remove(c) | vis.size() < 2 |
| TypeScript | Set<string> | vis.add(c) | vis.delete(c) | vis.size < 2 |
Sources: lcci/01.04.Palindrome Permutation/README_EN.md160-292
| Pattern | Time Complexity | Space Complexity | Use Case |
|---|---|---|---|
| Value-to-Index Mapping | $O(n)$ | $O(n)$ | Finding pairs, complements |
| Frequency Counting | $O(n)$ | $O(k)$ where $k$ is charset size | Anagrams, permutations |
| Toggle Set | $O(n)$ | $O(k)$ where $k$ is charset size | Parity checks |
Key Observations:
insert, lookup, delete) are $O(1)$ average caseSources: solution/0000-0099/0001.Two Sum/README.md77 lcci/01.02.Check Permutation/README.md56 lcci/01.04.Palindrome Permutation/README.md43
For problems with small character sets, bit manipulation can replace hash tables:
Bit Vector Approach: Use each bit in a 32-bit integer to represent one character's presence.
Java Implementation:
Advantages over Hash Table:
Limitations:
Sources: lcci/01.01.Is Unique/README.md42-50 lcci/01.01.Is Unique/Solution.java1-12 lcci/01.01.Is Unique/Solution.cpp1-14 lcci/01.01.Is Unique/Solution.go1-11
dict type with in operator for membershipcollections.Counter for frequency counting with += supportset type for unique elementsjava.util.HashMap<K,V> with .containsKey(), .put(), .get()cnt.merge(key, 1, Integer::sum) for countingstd::unordered_map<K,V> from <unordered_map>std::unordered_set<T> for set operationsmap[KeyType]ValueType with comma-ok idiom: val, ok := m[key]new Map<K,V>() with .has(), .get(), .set(){} work but less type-safe than Mapnew Set<T>() for unique elementsstd::collections::HashMap requires explicit import.get(&key) (reference) not .get(key) (move)map.entry(key).or_insert(0) += 1 for clean countingSources: solution/0000-0099/0001.Two Sum/Solution.py1-8 solution/0000-0099/0001.Two Sum/Solution.java1-13 solution/0000-0099/0001.Two Sum/Solution.cpp1-14 solution/0000-0099/0001.Two Sum/Solution.go1-11 solution/0000-0099/0001.Two Sum/Solution.ts1-11 solution/0000-0099/0001.Two Sum/Solution.rs1-15
The hash table pattern appears in multiple problem series:
For problems requiring order preservation or range queries, consider:
Sources: Directory structure from Problem Organization and Problem Series
Refresh this wiki
This wiki was recently refreshed. Please wait 6 days to refresh again.