Hash Table: Code Templates in 6 Languages
If you have not read the concept guide yet, start there for the intuition and the complexity analysis. This page gives you the code to memorize. Each template covers the same logic in JavaScript, Python, Java, C++, Go, and Ruby. All of them run in
Main Template: Frequency Counter
Count the occurrences of each element in a collection. This is the foundation for most other hash table work, from anagram checks to top-k frequency problems.
Use this for Ransom Note and as the first half of Intersection of Two Arrays II.
function frequencyCounter(arr) {
const freq = new Map();
for (const item of arr) {
// Read the existing count, default to 0 for a new key,
// then write back the incremented value in one step.
freq.set(item, (freq.get(item) || 0) + 1);
}
return freq;
}Code Breakdown
Key Variables
freq/counts: the map that holds one count per unique element.item/num: the current element being processed.count: the number of times the element has appeared so far.
Visual Mechanism
graph TD
A["Empty map"] --> B["Read next element"]
B --> C{"Is it already a key?"}
C -->|No| D["Insert with count 1"]
C -->|Yes| E["Add 1 to its count"]
D --> F["More elements?"]
E --> F
F -->|Yes| B
F -->|No| G["Return the map"]
Critical Sections
The initialization creates the empty map, and the default value matters. Ruby uses Hash.new(0), C++ operator[] inserts a zero for new keys, Java uses getOrDefault, and Python reads with get(item, 0). All of these make the first occurrence of an element count as 1 instead of crashing or counting as 0.
The update step reads the current count, adds 1, and writes it back. In most languages the read and the write happen in the same expression, which is easy to misread under time pressure. Practice reading it as “read, increment, write.”
The loop visits each element exactly once. Nothing else is needed, and the iteration order of the map never matters for counting.
Variations
1. Complement Search
Use this when two elements must satisfy a relation, like two numbers summing to a target. For each element, check whether the element that would complete the pair has been seen, then store the current element.
Time
Use this for Two Sum .
function complementSearch(nums, target) {
const seen = new Map();
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
// Check before storing so the current element
// cannot pair with itself.
if (seen.has(complement)) {
return [seen.get(complement), i];
}
seen.set(nums[i], i);
}
return [];
}2. Grouping Pattern
Use this when elements share a canonical form, like anagrams sharing sorted letters. The canonical form becomes the key, and each key collects a list.
Time
Use this for Group Anagrams .
function groupByKey(arr, keyFunction) {
const groups = new Map();
for (const item of arr) {
const key = keyFunction(item);
// Insert an empty list on first sight of a key,
// then append. The list must exist before the push.
if (!groups.has(key)) {
groups.set(key, []);
}
groups.get(key).push(item);
}
return Array.from(groups.values());
}3. Count-Down Comparison
Use this when one collection must be built from another, like a ransom note from a magazine. Count the source collection, then decrement counts while consuming the target.
Time
function canBeBuilt(target, source) {
const counts = new Map();
for (const ch of source) {
counts.set(ch, (counts.get(ch) || 0) + 1);
}
for (const ch of target) {
// A missing key or an exhausted count means
// the source cannot supply this character.
if (!counts.has(ch) || counts.get(ch) === 0) {
return false;
}
counts.set(ch, counts.get(ch) - 1);
}
return true;
}Now head to the practice problems to apply these templates to real interview questions.