⚡ Play a quiz
HomeLearnData Structures & AlgorithmsHashing › Frequency counting
Lesson 2 of 2 · Hashing

Frequency Counting Patterns with Hash Maps

Hashing100%

Most hash-map interview questions are one of three patterns wearing different clothes: count things, remember what you have already seen, or group items by a computed key. Recognising which one a question is turns a hard problem into a five-line loop.

Read time
7 min
Track
Data Structures & Algorithms
Sections
4
Practice
6

Pattern 1 — count occurrences

Count, then find the most frequent
Map<String, Integer> counts = new HashMap<>();
for (String word : words) {
    counts.merge(word, 1, Integer::sum);
}

String mostCommon = counts.entrySet().stream()
        .max(Map.Entry.comparingByValue())
        .map(Map.Entry::getKey)
        .orElse(null);
tip

When the key space is small, skip the map

For lowercase letters, int[26] is faster and simpler than a HashMap — no hashing, no boxing, perfect cache locality. Use a map when the key space is large or unknown.

Pattern 2 — have I seen this before?

A set answers membership in O(1), which converts "for each element, scan the rest" from O(n2) into one pass. The classic example is two sum on an unsorted array — where two pointers is unavailable because sorting would destroy the original indices.

Two sum, unsorted, one pass
int[] twoSum(int[] a, int target) {
    Map<Integer, Integer> seen = new HashMap<>();   // value -> index
    for (int i = 0; i < a.length; i++) {
        Integer j = seen.get(target - a[i]);
        if (j != null) return new int[]{j, i};
        seen.put(a[i], i);
    }
    return new int[]{-1, -1};
}

O(n) time, O(n) space. The trade is explicit and worth saying out loud: you spend memory to buy a linear scan.

NESTED SCAN — for each element, search the rest 2 7 11 15 n + (n-1) + … comparisons O(n²) time, O(1) space SEEN-BEFORE SET — one pass, ask about the past 2 7 11 15 at 7, target 9 have I seen 9 - 7 = 2 ? seen = { 2 } yes → O(1) O(n) time, O(n) space — memory spent to buy a single pass. Say the trade out loud.
The set is what removes the inner loop: instead of searching the rest of the array, you ask one question about everything already behind you.

Pattern 3 — group by a computed key

When items belong together under some derived property, compute that property and use it as the map key. "Group anagrams" is the standard example: two words are anagrams exactly when their sorted characters match, so the sorted string is the key.

Group anagrams
List<List<String>> groupAnagrams(String[] words) {
    Map<String, List<String>> groups = new HashMap<>();
    for (String word : words) {
        char[] chars = word.toCharArray();
        Arrays.sort(chars);
        String key = new String(chars);          // the canonical form
        groups.computeIfAbsent(key, k -> new ArrayList<>()).add(word);
    }
    return new ArrayList<>(groups.values());
}

O(n x k log k) for n words of length k, dominated by sorting each word. Using a 26-character count signature as the key instead removes the sort and brings it to O(n x k) — a good optimisation to offer once the first version works.

Choosing the right structure

Which map or set to reach for
NeedJavaPython
Fastest lookup, order irrelevantHashMap / HashSetdict / set
Keys in sorted order, range queriesTreeMap / TreeSetsorted() or the bisect module
Insertion order preservedLinkedHashMapdict (guaranteed since 3.7)
Countingmerge(k, 1, Integer::sum)collections.Counter

Key takeaways

  • Count, seen-before and group-by cover most hash-map interview questions.
  • A set turns an O(n squared) nested scan into a single O(n) pass.
  • For a small fixed key space, an array beats a hash map on every axis.
  • Group-by works by computing a canonical form and using it as the key.

Practice

ProblemPatternLevel
Two sum on an unsorted arraySeen-before mapEasy
Contains duplicateSet membershipEasy
First unique character in a stringFrequency countEasy
Group anagramsGroup by canonical keyMedium
Top k frequent elementsCount + heap or bucket sortMedium
Longest consecutive sequenceSet membershipMedium

Frequently asked questions

When should I use a hash map instead of sorting?

When you need O(n) rather than O(n log n), when the original element order matters, or when you need counts rather than order. Sorting wins when the question needs ordering, ranges, or O(1) extra space.

How do you find duplicates in an array efficiently?

Walk the array once, checking membership in a set before inserting. That is O(n) time and O(n) space, against O(n log n) for sorting or O(n squared) for a nested scan.

Why use an array instead of a hash map for character counts?

For a fixed small alphabet, array indexing is direct with no hashing, no boxing and better cache locality. int[26] or int[128] is both faster and simpler than a map.

Test yourself on Hashing

Reading is not recall. Take a timed quiz on this topic solo, or share a room code and battle friends on it.

⚡ Start the Hashing quiz

More in Hashing