LeetCopilot Logo
LeetCopilot
LeetCode Pattern/Hash Map/Hash Map Pattern: Complete Guide With Templates (Python/Java/JS)

Hash Map Pattern: Complete Guide With Templates (Python/Java/JS)

LeetCopilot Team
Dec 10, 2025
25 min read
Hash MapLeetCode PatternData StructuresInterview Prep
Master the hash map pattern beyond basic dictionaries. Learn all 6 core patterns, recognition strategies, multi-language templates, and the decision framework that turns O(n²) brute force into O(n) elegance.

You're in a coding interview. The problem asks you to find two numbers that sum to a target. You know you need a hash map... but then what?

Do you store the number as the key or the index? Do you check for the complement before or after adding to the map? What if there are duplicates?

This is the gap between knowing about hash maps and mastering the hash map pattern.

Hash maps are one of the most powerful tools in algorithm design. They transform O(n²) brute-force solutions into O(n) elegance by trading space for time. But the pattern isn't just "use a dictionary"—it's a family of techniques with distinct recognition signals, templates, and pitfalls.

This guide is the pillar article for everything hash map:

  • What the hash map pattern really is (beyond "use a dict")
  • How to instantly recognize hash map problems
  • The 6 core hash map patterns with templates
  • Deep-dive examples with diagrams and debugging notes
  • When hash maps beat (and lose to) other data structures
  • A senior-level debugging checklist

If you internalize this, hash maps stop being a guess and become a reliable O(1) lookup weapon you can deploy confidently in any interview.

What Is the Hash Map Pattern?

At a high level, the hash map pattern is a way to achieve O(1) lookups by trading space for time. Instead of searching through data linearly or sorting it first, you preprocess information into a hash map for instant access.

The core concept: trading space for time

The fundamental trade-off:

  • Without hash map: Search through array → O(n) per lookup
  • With hash map: Store in hash map → O(1) per lookup, O(n) space

Think of it as building an index:

text
Array: [7, 2, 5, 8, 1, 3]

Without hash map (brute force):
  To find if 5 exists: scan all elements → O(n)

With hash map:
  Build: {7: 0, 2: 1, 5: 2, 8: 3, 1: 4, 3: 5}
  To find if 5 exists: map.has(5) → O(1)

Real-world analogy

Imagine you're looking for a book in a library:

  • Without index (array): Walk through every shelf until you find it
  • With index (hash map): Look up the book in the catalog, go directly to the shelf

The catalog takes up space, but it makes finding books instant.

Why interviews love this pattern

Hash map problems test:

  • Your ability to recognize O(1) lookup opportunities
  • Your understanding of key/value design (what to store where)
  • Your discipline around edge cases (duplicates, collisions, existence checks)

It's also a great discriminator: many candidates know "use a dict", but far fewer can articulate why this key/value pair is optimal and debug it under pressure.

Core Intuition: How Hash Maps Actually "Think"

At an intuitive level, the hash map pattern does three things:

  1. Identify what you need to look up quickly
  2. Design the key/value pair that enables O(1) access
  3. Handle edge cases (duplicates, missing keys, collisions)

The lookup trade-off

Every hash map solution makes a conscious trade-off:

text
Time saved:   O(n) → O(1) per lookup
Space cost:   O(1) → O(n) for the map

This trade-off is worth it when:

  • You need multiple lookups (amortized benefit)
  • You need to check existence frequently
  • You need to find complements or pairs
  • You need to group or categorize data

Key selection: what makes a good hash map key?

The key is what you'll look up. Good keys are:

  1. Unique (or uniquely identify what you care about)
  2. Immutable (won't change after insertion)
  3. Hashable (can be converted to a hash code)

Examples:

  • ✅ Numbers, strings, tuples (immutable)
  • ❌ Lists, sets, dicts (mutable in most languages)

Value selection: what to store?

The value is what you need when you find the key. Common choices:

  • Index: Where this element appears
  • Count: How many times it appears
  • Boolean: Whether it exists
  • List: All positions where it appears
  • Object: Complex associated data

The "seen before" mental model

Many hash map problems boil down to:

"Have I seen this before? If yes, do something with the previous occurrence."

Examples:

  • Two Sum: "Have I seen the complement before?"
  • Contains Duplicate: "Have I seen this number before?"
  • Group Anagrams: "Have I seen this pattern before?"

This mental model helps you recognize hash map opportunities instantly.

How to Identify Hash Map Problems Instantly

You don't want to recognize hash maps halfway through a brute-force attempt. Here's a checklist and language cues to spot them immediately.

Quick checklist

Use hash map if:

  • You need to find something quickly (O(1) lookup)
  • You need to check if something exists
  • You need to count frequencies
  • You need to find complements or pairs (target - current)
  • You need to group by a property
  • You need to detect duplicates

If any of these are true, consider a hash map first.

Phrases in problem statements

Strong hash map signals:

  • "find two numbers that..."
  • "check if ... exists"
  • "count the number of..."
  • "group ... by ..."
  • "find all ... that appear ..."
  • "contains duplicate"
  • "first unique / non-repeating"

Examples:

  • "Find two numbers that sum to target" → Two Sum pattern
  • "Group anagrams together" → Grouping pattern
  • "Find the first non-repeating character" → Frequency counter

Hash map vs. set vs. array

Quick decision tree:

code
Do you need associated values (not just presence)?
├─ Yes → Use hash map
└─ No → Use hash set

Do you need O(1) lookup by arbitrary keys?
├─ Yes → Use hash map/set
└─ No → Use array (if indexed access is enough)

When NOT to use hash maps

Don't use hash maps when:

  • ❌ You need ordered data → Use TreeMap/sorted structure
  • ❌ You need range queries → Use prefix sum or segment tree
  • ❌ Memory is severely constrained → Use in-place techniques
  • ❌ Dataset is tiny (< 10 elements) → Array scan is fine
  • ❌ You need sorted iteration → Use TreeMap or sort first

For deeper analysis, see When NOT to Use Hash Maps.

The 6 Core Hash Map Patterns

Hash map isn't one pattern—it's six distinct techniques that solve different types of problems. Understanding which pattern to use is the key to mastering hash maps.

Pattern 1: Frequency Counter

Definition: Count how many times each element appears.

When to use:

  • "Count occurrences"
  • "Find most/least frequent"
  • "First unique character"
  • "Valid anagram"

Key/Value design:

  • Key: The element
  • Value: Count of occurrences

Example:

python
# Count character frequencies
freq = {}
for char in s:
    freq[char] = freq.get(char, 0) + 1

See: Frequency Counter Pattern

Pattern 2: Index Mapping

Definition: Store the position(s) where each element appears.

When to use:

  • "Find where element appears"
  • "Distance between occurrences"
  • "Last seen position"
  • Two Sum (store index for complement lookup)

Key/Value design:

  • Key: The element
  • Value: Index (or list of indices)

Example:

python
# Store last seen index
index_map = {}
for i, num in enumerate(nums):
    index_map[num] = i

See: Index Mapping Pattern

Pattern 3: Complement Finder (Two Sum Pattern)

Definition: For each element, check if its complement exists.

When to use:

  • "Find two numbers that sum to target"
  • "Pair with difference k"
  • "Check if complement exists"

Key/Value design:

  • Key: The number
  • Value: Index (to return positions)

Example:

python
# Two Sum
seen = {}
for i, num in enumerate(nums):
    complement = target - num
    if complement in seen:
        return [seen[complement], i]
    seen[num] = i

See: Two Sum Pattern

Pattern 4: Grouping / Categorization

Definition: Group elements by a computed property.

When to use:

  • "Group anagrams"
  • "Group by pattern"
  • "Categorize by property"

Key/Value design:

  • Key: The grouping property (sorted string, pattern, hash)
  • Value: List of elements in that group

Example:

python
# Group anagrams
groups = {}
for word in words:
    key = ''.join(sorted(word))
    if key not in groups:
        groups[key] = []
    groups[key].append(word)

See: Grouping Pattern

Pattern 5: Seen Tracker

Definition: Track whether you've seen an element before.

When to use:

  • "Contains duplicate"
  • "Detect cycle"
  • "First repeating element"

Key/Value design:

  • Key: The element
  • Value: Boolean (or just use a set)

Example:

python
# Contains duplicate
seen = set()
for num in nums:
    if num in seen:
        return True
    seen.add(num)
return False

Note: Often a set is sufficient (don't need values).

Pattern 6: Prefix Sum + Hash Map

Definition: Store prefix sums to find subarrays with target sum.

When to use:

  • "Subarray sum equals k"
  • "Continuous subarray sum"
  • "Subarray sum divisible by k"
  • Array has negative numbers (can't use sliding window)

Key/Value design:

  • Key: Prefix sum
  • Value: Frequency (how many times this sum appeared)

Example:

python
# Subarray sum equals k
count = 0
prefix_sum = 0
sum_count = {0: 1}  # Critical: handle subarrays from index 0

for num in nums:
    prefix_sum += num
    if prefix_sum - k in sum_count:
        count += sum_count[prefix_sum - k]
    sum_count[prefix_sum] = sum_count.get(prefix_sum, 0) + 1

See: Prefix Sum + Hash Map

Universal Templates (Multi-Language)

For interview performance, you want one mental template per pattern and language.

Python Templates

Pattern 1: Frequency Counter

python
from collections import Counter

# Approach 1: Using Counter (recommended)
freq = Counter(nums)
# freq[x] gives count of x

# Approach 2: Manual dict
freq = {}
for num in nums:
    freq[num] = freq.get(num, 0) + 1

# Approach 3: defaultdict
from collections import defaultdict
freq = defaultdict(int)
for num in nums:
    freq[num] += 1

Pattern 2: Index Mapping

python
# Store last index
index_map = {}
for i, num in enumerate(nums):
    index_map[num] = i

# Store all indices
from collections import defaultdict
index_map = defaultdict(list)
for i, num in enumerate(nums):
    index_map[num].append(i)

Pattern 3: Two Sum (Complement)

python
def two_sum(nums, target):
    seen = {}
    for i, num in enumerate(nums):
        complement = target - num
        if complement in seen:
            return [seen[complement], i]
        seen[num] = i
    return []

Pattern 4: Grouping

python
from collections import defaultdict

groups = defaultdict(list)
for item in items:
    key = compute_key(item)  # e.g., sorted(item)
    groups[key].append(item)

Pattern 5: Seen Tracker

python
# Use set (more efficient than dict)
seen = set()
for num in nums:
    if num in seen:
        return True
    seen.add(num)
return False

Pattern 6: Prefix Sum + Hash Map

python
def subarray_sum(nums, k):
    count = 0
    prefix_sum = 0
    sum_count = {0: 1}
    
    for num in nums:
        prefix_sum += num
        if prefix_sum - k in sum_count:
            count += sum_count[prefix_sum - k]
        sum_count[prefix_sum] = sum_count.get(prefix_sum, 0) + 1
    
    return count

Java Templates

Frequency Counter

java
// Using HashMap
Map<Integer, Integer> freq = new HashMap<>();
for (int num : nums) {
    freq.put(num, freq.getOrDefault(num, 0) + 1);
}

Two Sum

java
public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> seen = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (seen.containsKey(complement)) {
            return new int[] {seen.get(complement), i};
        }
        seen.put(nums[i], i);
    }
    return new int[] {};
}

Grouping

java
Map<String, List<String>> groups = new HashMap<>();
for (String word : words) {
    char[] chars = word.toCharArray();
    Arrays.sort(chars);
    String key = new String(chars);
    
    groups.putIfAbsent(key, new ArrayList<>());
    groups.get(key).add(word);
}

JavaScript Templates

Frequency Counter

javascript
// Using Map
const freq = new Map();
for (const num of nums) {
  freq.set(num, (freq.get(num) || 0) + 1);
}

// Using object (for simple keys)
const freq = {};
for (const num of nums) {
  freq[num] = (freq[num] || 0) + 1;
}

Two Sum

javascript
function twoSum(nums, target) {
  const seen = new Map();
  for (let i = 0; i < nums.length; i++) {
    const complement = target - nums[i];
    if (seen.has(complement)) {
      return [seen.get(complement), i];
    }
    seen.set(nums[i], i);
  }
  return [];
}

Grouping

javascript
const groups = new Map();
for (const word of words) {
  const key = word.split('').sort().join('');
  if (!groups.has(key)) {
    groups.set(key, []);
  }
  groups.get(key).push(word);
}

Hash Map in Action: Step-by-Step Examples

Let's walk through three canonical hash map problems with diagrams and pitfalls.

Example 1: Two Sum (LeetCode 1)

Problem: Given an array of integers nums and an integer target, return indices of the two numbers that add up to target.

This is the poster child for complement search:

  • Pattern: Complement finder
  • Key: The number
  • Value: Its index

Window evolution

For nums = [2, 7, 11, 15], target = 9:

text
Step   i  num  complement  seen           action
-----  -  ---  ----------  -------------  ----------------------------
0      0  2    9-2=7       {}             7 not in seen, add {2: 0}
1      1  7    9-7=2       {2: 0}         2 in seen! return [0, 1]

Python solution

python
def twoSum(nums: List[int], target: int) -> List[int]:
    seen = {}
    for i, num in enumerate(nums):
        complement = target - num
        if complement in seen:
            return [seen[complement], i]
        seen[num] = i
    return []

Key points:

  • Check for complement before adding current number (handles duplicates correctly)
  • Store index as value (problem asks for indices)
  • Complexity: O(n) time, O(n) space

Common pitfalls:

  • Adding to map before checking (fails when target = 2 * num)
  • Using value as key and index as value backwards
  • Not handling the case where no solution exists

For more on this pattern, see Two Sum Pattern.

Example 2: Group Anagrams (LeetCode 49)

Problem: Given an array of strings strs, group the anagrams together.

This is a classic grouping pattern:

  • Pattern: Grouping/categorization
  • Key: Sorted string (canonical form)
  • Value: List of original strings

Intuition

Anagrams have the same characters, just rearranged. If we sort each word, anagrams become identical:

  • "eat" → "aet"
  • "tea" → "aet"
  • "ate" → "aet"

Use the sorted string as the grouping key.

Python solution

python
from collections import defaultdict

def groupAnagrams(strs: List[str]) -> List[List[str]]:
    groups = defaultdict(list)
    
    for word in strs:
        # Sorted string is the key
        key = ''.join(sorted(word))
        groups[key].append(word)
    
    return list(groups.values())

Example trace:

text
Input: ["eat", "tea", "tan", "ate", "nat", "bat"]

Step 1: "eat" → key="aet" → groups = {"aet": ["eat"]}
Step 2: "tea" → key="aet" → groups = {"aet": ["eat", "tea"]}
Step 3: "tan" → key="ant" → groups = {"aet": ["eat", "tea"], "ant": ["tan"]}
Step 4: "ate" → key="aet" → groups = {"aet": ["eat", "tea", "ate"], "ant": ["tan"]}
Step 5: "nat" → key="ant" → groups = {"aet": ["eat", "tea", "ate"], "ant": ["tan", "nat"]}
Step 6: "bat" → key="abt" → groups = {"aet": ["eat", "tea", "ate"], "ant": ["tan", "nat"], "abt": ["bat"]}

Output: [["eat", "tea", "ate"], ["tan", "nat"], ["bat"]]

Key points:

  • Sorting creates a canonical form (same for all anagrams)
  • defaultdict(list) avoids checking if key exists
  • Complexity: O(n * k log k) where n = number of words, k = max word length

Alternative approaches:

  1. Character count as key: Use tuple of counts instead of sorted string
  2. Prime number product: Assign each letter a prime, multiply (rare, risk of overflow)

For deep dive, see Group Anagrams Deep Dive.

Example 3: Subarray Sum Equals K (LeetCode 560)

Problem: Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals k.

This is a prefix sum + hash map pattern:

  • Pattern: Prefix sum with complement search
  • Key: Prefix sum
  • Value: Frequency of that sum

Why hash map is needed

Brute force: Check all subarrays → O(n²)

Key insight: If prefix[j] - prefix[i] = k, then subarray from i+1 to j has sum k.

Rearrange: prefix[i] = prefix[j] - k

So for each position j, check if prefix[j] - k exists in our map.

Python solution

python
def subarraySum(nums: List[int], k: int) -> int:
    count = 0
    prefix_sum = 0
    sum_count = {0: 1}  # Critical: handle subarrays starting from index 0
    
    for num in nums:
        prefix_sum += num
        
        # Check if (prefix_sum - k) exists
        if prefix_sum - k in sum_count:
            count += sum_count[prefix_sum - k]
        
        # Add current prefix sum to map
        sum_count[prefix_sum] = sum_count.get(prefix_sum, 0) + 1
    
    return count

Example trace:

text
nums = [1, 2, 3], k = 3

Step   num  prefix  check           sum_count                  count
-----  ---  ------  --------------  -------------------------  -----
init   -    0       -               {0: 1}                     0
0      1    1       1-3=-2 (no)     {0: 1, 1: 1}               0
1      2    3       3-3=0 (yes!)    {0: 1, 1: 1, 3: 1}         1
2      3    6       6-3=3 (yes!)    {0: 1, 1: 1, 3: 1, 6: 1}   2

Found 2 subarrays: [1,2] and [3]

Key points:

  • Initialize with {0: 1} to handle subarrays starting from index 0
  • Update map after checking (order matters!)
  • Works with negative numbers (unlike sliding window)

Common mistakes:

  • Forgetting {0: 1} initialization
  • Updating map before checking
  • Confusing this with sliding window

For debugging guide, see Subarray Sum Mistakes.

Advanced Techniques & Variations

Once you're comfortable with basic patterns, you'll see richer variations.

Multi-key hash maps (tuple keys)

Sometimes you need to group by multiple properties:

python
# Group by (row, column sum)
groups = {}
for item in items:
    key = (item.row, item.col_sum)
    if key not in groups:
        groups[key] = []
    groups[key].append(item)

Python: Tuples are hashable (immutable)
Java: Create composite key class with proper hashCode() and equals()
JavaScript: Use string concatenation or Map with array keys (careful!)

Hash map with custom objects

For complex keys, you need proper hash functions:

Java:

java
class Point {
    int x, y;
    
    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
    
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Point)) return false;
        Point p = (Point) obj;
        return x == p.x && y == p.y;
    }
}

Map<Point, Integer> map = new HashMap<>();

Python:

python
# Use tuple or frozen dataclass
from dataclasses import dataclass

@dataclass(frozen=True)
class Point:
    x: int
    y: int

map = {Point(1, 2): "value"}

Ordered hash maps

When you need insertion order:

Python: dict (ordered since Python 3.7) or OrderedDict
Java: LinkedHashMap
JavaScript: Map (maintains insertion order)

Hash map vs. hash set decision

Quick rule:

  • Need associated values? → Hash map
  • Only need presence check? → Hash set
python
# Contains Duplicate - set is enough
def containsDuplicate(nums):
    return len(nums) != len(set(nums))

# Two Sum - need indices, use map
def twoSum(nums, target):
    seen = {}  # map, not set
    for i, num in enumerate(nums):
        if target - num in seen:
            return [seen[target - num], i]
        seen[num] = i

For detailed comparison, see Hash Map vs Hash Set.

Debugging Hash Maps: A Senior Engineer's Checklist

If your hash map solution fails, use this checklist:

1. Key/value pair design

Is your key unique enough?

  • Wrong: Using index as key when you need to look up by value
  • Right: Using value as key when searching for it

Is your key immutable?

  • Wrong: Using list as key in Python
  • Right: Using tuple or frozen set

Is your value what you actually need?

  • Wrong: Storing boolean when you need the index
  • Right: Storing index for Two Sum

2. Existence checks

Are you checking before accessing?

python
# Wrong - may crash
value = map[key]

# Right
if key in map:
    value = map[key]
# Or use .get() with default
value = map.get(key, default)

3. Update order

Are you updating the map at the right time?

python
# Two Sum - check BEFORE adding
if complement in seen:
    return [seen[complement], i]
seen[num] = i  # Add after checking

# Subarray Sum - check BEFORE adding
if prefix_sum - k in sum_count:
    count += sum_count[prefix_sum - k]
sum_count[prefix_sum] = sum_count.get(prefix_sum, 0) + 1

4. Duplicate handling

How are you handling duplicates?

  • Store first occurrence?
  • Store last occurrence?
  • Store count?
  • Store all occurrences (list)?

See Handling Duplicates.

5. Edge cases

Did you test these?

  • Empty array
  • Single element
  • All duplicates
  • No solution exists
  • Multiple solutions

6. Memory overhead

Is the hash map too large?

  • Can you use a set instead of a map?
  • Can you use sliding window to limit map size?
  • Can you use in-place marking for arrays?

See Memory Optimization.

Time & Space Complexity Analysis

Best, average, worst case

Hash map operations:

OperationAverageWorst CaseNotes
InsertO(1)O(n)Worst case: all keys collide
LookupO(1)O(n)Worst case: all keys collide
DeleteO(1)O(n)Worst case: all keys collide

In practice: Modern hash maps (Python dict, Java HashMap, JS Map) have excellent average-case performance. Worst case is extremely rare with good hash functions.

Hash collision impact

What is a collision?
When two different keys produce the same hash code.

How it's handled:

  • Chaining: Store colliding elements in a linked list
  • Open addressing: Find next available slot

Impact on complexity:

  • With good hash function: O(1) average
  • With poor hash function: degrades to O(n)

In interviews: You can assume O(1) unless specifically asked about collisions.

Space-time tradeoffs

text
Without hash map:
  Time: O(n²) (nested loops)
  Space: O(1)

With hash map:
  Time: O(n) (single pass)
  Space: O(n) (store all elements)

Trade-off: Spend O(n) space to save O(n²) → O(n) time

When it's worth it:

  • Large datasets (n > 100)
  • Multiple queries
  • Time is more critical than space

When it's not worth it:

  • Tiny datasets (n < 10)
  • Severe memory constraints
  • One-time operation on small data

Common Mistakes & How to Avoid Them

Mistake 1: Wrong key/value choice

Wrong:

python
# Two Sum - storing value as value (can't look up by value!)
seen = {}
for i, num in enumerate(nums):
    seen[i] = num  # Wrong: key should be num, value should be i

Correct:

python
seen = {}
for i, num in enumerate(nums):
    seen[num] = i  # Right: key is num (what we search), value is index (what we need)

Mistake 2: Not handling duplicates

Wrong:

python
# Two Sum - adding before checking fails when target = 2 * num
seen[num] = i
if target - num in seen:
    return [seen[target - num], i]

Correct:

python
# Check before adding
if target - num in seen:
    return [seen[target - num], i]
seen[num] = i

Mistake 3: Forgetting existence check

Wrong:

python
# May crash if key doesn't exist
count = freq[char]

Correct:

python
# Use .get() with default
count = freq.get(char, 0)

# Or check first
if char in freq:
    count = freq[char]

Mistake 4: Using mutable keys

Wrong:

python
# Lists are not hashable in Python
key = [1, 2, 3]
map[key] = "value"  # TypeError!

Correct:

python
# Use tuple (immutable)
key = (1, 2, 3)
map[key] = "value"

For comprehensive debugging, see Common Hash Map Mistakes.

When NOT to Use Hash Maps

Hash maps are powerful, but not always optimal.

Case 1: You need ordered data

Problem: Iterate through keys in sorted order

Why hash map fails: Hash maps don't maintain order (or maintain insertion order, not sorted order)

Use instead: TreeMap (Java), sorted dict (Python sortedcontainers), or sort the keys

Case 2: You need range queries

Problem: "Find all elements between x and y"

Why hash map fails: No efficient way to query ranges

Use instead: Balanced BST, segment tree, or sorted array with binary search

Case 3: Memory is severely constrained

Problem: O(n) space is too much

Why hash map fails: Requires extra space

Use instead: In-place algorithms, two pointers, bit manipulation

Case 4: Dataset is very small

Problem: Array has 5 elements

Why hash map fails: Overhead of hash map isn't worth it

Use instead: Simple array scan (O(n) is fine for small n)

Case 5: You only need presence (not values)

Problem: Check if element exists

Why hash map is overkill: Don't need key-value pairs

Use instead: Hash set (more memory efficient)

For detailed analysis, see When NOT to Use Hash Maps.

Practice Strategy & Problem Sets

Beginner problems

Start here to build pattern recognition:

  1. Two Sum (#1) - Complement search
  2. Contains Duplicate (#217) - Seen tracker (use set)
  3. Valid Anagram (#242) - Frequency counter
  4. Majority Element (#169) - Frequency counter
  5. Single Number (#136) - Bit manipulation or hash set

Intermediate problems

Build fluency with variations:

  1. Group Anagrams (#49) - Grouping pattern
  2. Top K Frequent Elements (#347) - Frequency + heap
  3. Subarray Sum Equals K (#560) - Prefix sum + hash map
  4. Longest Substring Without Repeating Characters (#3) - Hash map + sliding window
  5. 4Sum II (#454) - Multi-map complement search
  6. Isomorphic Strings (#205) - Bidirectional mapping
  7. Word Pattern (#290) - Bidirectional mapping

Advanced problems

Master edge cases and optimizations:

  1. Minimum Window Substring (#76) - Hash map + sliding window
  2. Longest Consecutive Sequence (#128) - Hash set with clever lookup
  3. Insert Delete GetRandom O(1) (#380) - Hash map + array
  4. LRU Cache (#146) - Hash map + doubly linked list
  5. All O`one Data Structure (#432) - Hash map + doubly linked list
  6. Alien Dictionary (#269) - Hash map for graph representation

Practice strategy

  1. Start with recognition: Before coding, identify the pattern
  2. Design key/value first: Write down what you'll store
  3. Handle edge cases: Empty, single element, duplicates
  4. Optimize: Can you use set instead? Can you reduce space?
  5. Explain complexity: Practice articulating O(1) average case

Summary & Next Steps

The hash map pattern is a fundamental tool that transforms O(n²) brute force into O(n) elegance by trading space for time.

Key principles:

  • Recognize the 6 core patterns (frequency, index, complement, grouping, seen, prefix sum)
  • Design key/value pairs intentionally (what to look up, what to store)
  • Handle edge cases (duplicates, missing keys, collisions)
  • Choose wisely (hash map vs. set vs. array vs. tree)

The mental model:

"Have I seen this before? If yes, what do I need to know about it?"

When to use hash maps:

  • ✅ Need O(1) lookup
  • ✅ Check existence
  • ✅ Count frequencies
  • ✅ Find complements/pairs
  • ✅ Group by property

When NOT to use hash maps:

  • ❌ Need ordered data
  • ❌ Need range queries
  • ❌ Severe memory constraints
  • ❌ Tiny datasets

Next steps:

  1. Master the Frequency Counter Pattern for counting problems
  2. Deep dive into Two Sum Pattern for complement search
  3. Learn Grouping Pattern for categorization
  4. Study Common Hash Map Mistakes to avoid pitfalls
  5. Practice the beginner problem set to build pattern recognition

Master these patterns, and hash maps stop being a guess and become a reliable weapon in your interview arsenal.

Want to Practice LeetCode Smarter?

LeetCopilot is a free browser extension that enhances your LeetCode practice with AI-powered hints, personalized study notes, and realistic mock interviews — all designed to accelerate your coding interview preparation.

Also compatible with Edge, Brave, and Opera

Related Tutorials