You're solving a hash map problem. An element appears twice. What do you do?
Overwrite the old value? Keep the first? Store both?
Handling duplicates correctly is one of the trickiest parts of hash map problems. Get it wrong, and your solution fails on edge cases.
This guide shows you the 4 duplicate strategies and exactly when to use each.
The Four Duplicate Strategies
Strategy 1: Store Last Occurrence
When: Need most recent position, or any valid occurrence
How: Always overwrite
index_map = {}
for i, num in enumerate(nums):
index_map[num] = i # Overwrites previousResult: {num: last_index}
Strategy 2: Store First Occurrence
When: Need earliest position, or first unique element
How: Only store if not exists
index_map = {}
for i, num in enumerate(nums):
if num not in index_map:
index_map[num] = i # Only store firstResult: {num: first_index}
Strategy 3: Count Occurrences
When: Need frequency, not positions
How: Increment counter
from collections import Counter
freq = Counter(nums)
# Or manually
freq = {}
for num in nums:
freq[num] = freq.get(num, 0) + 1Result: {num: count}
Strategy 4: Store All Occurrences
When: Need all positions where element appears
How: Append to list
from collections import defaultdict
index_map = defaultdict(list)
for i, num in enumerate(nums):
index_map[num].append(i)Result: {num: [index1, index2, ...]}
When to Use Each Strategy
Use Last Occurrence When:
Problem type: Two Sum, Contains Duplicate II
Why: Need any valid pair, most recent is fine
Example: Two Sum
def twoSum(nums, target):
seen = {}
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = i # Store last (overwrites)Why it works: We check before adding, so we never use the same index twice.
Example: Contains Duplicate II
def containsNearbyDuplicate(nums, k):
index_map = {}
for i, num in enumerate(nums):
if num in index_map:
if i - index_map[num] <= k:
return True
index_map[num] = i # Update to latest
return FalseWhy it works: We always want distance from most recent occurrence.
Use First Occurrence When:
Problem type: First Unique Character, Find First Duplicate
Why: Need earliest position
Example: First Unique Character
def firstUniqChar(s):
# Store first index and count
char_info = {}
for i, char in enumerate(s):
if char not in char_info:
char_info[char] = [i, 1] # [first_index, count]
else:
char_info[char][1] += 1 # Increment count
# Find minimum first index with count 1
result = float('inf')
for first_idx, count in char_info.values():
if count == 1:
result = min(result, first_idx)
return result if result != float('inf') else -1Why it works: We need the first unique character, not the last.
Simpler approach (using Counter):
from collections import Counter
def firstUniqChar(s):
freq = Counter(s)
for i, char in enumerate(s):
if freq[char] == 1:
return i
return -1Use Count When:
Problem type: Frequency-based problems, Valid Anagram, Top K Frequent
Why: Only care about how many times, not where
Example: Valid Anagram
from collections import Counter
def isAnagram(s, t):
return Counter(s) == Counter(t)Example: Top K Frequent Elements
from collections import Counter
import heapq
def topKFrequent(nums, k):
freq = Counter(nums)
return heapq.nlargest(k, freq.keys(), key=freq.get)Why it works: We only need counts, not positions.
Use All Occurrences When:
Problem type: Find All Anagrams, Intersection of Arrays
Why: Need every position
Example: Find All Anagrams
from collections import Counter
def findAnagrams(s, p):
if len(p) > len(s):
return []
result = []
p_count = Counter(p)
window_count = Counter(s[:len(p)])
if window_count == p_count:
result.append(0) # Store all valid indices
for i in range(len(p), len(s)):
window_count[s[i]] += 1
left_char = s[i - len(p)]
window_count[left_char] -= 1
if window_count[left_char] == 0:
del window_count[left_char]
if window_count == p_count:
result.append(i - len(p) + 1) # Store all
return resultExample: Intersection of Two Arrays II
from collections import Counter
def intersect(nums1, nums2):
count1 = Counter(nums1)
count2 = Counter(nums2)
result = []
for num in count1:
if num in count2:
# Add min(count1[num], count2[num]) times
result.extend([num] * min(count1[num], count2[num]))
return resultThe Two Sum Duplicate Trap
This is the most common mistake with duplicates.
The Problem
nums = [3, 3], target = 6What should happen?
- We need two different 3's
- Should return
[0, 1]
Wrong Approach (add before check)
❌ Fails:
def twoSum(nums, target):
seen = {}
for i, num in enumerate(nums):
seen[num] = i # Add FIRST
if target - num in seen:
return [seen[target - num], i]
# i=0: seen={3:0}, check 6-3=3, found! return [0, 0] ❌Why it fails: We find the same element at index 0.
Correct Approach (check before add)
✅ Works:
def twoSum(nums, target):
seen = {}
for i, num in enumerate(nums):
if target - num in seen: # Check FIRST
return [seen[target - num], i]
seen[num] = i # Add AFTER
# i=0: check 6-3=3 (not found), add {3:0}
# i=1: check 6-3=3 (found!), return [0, 1] ✓Why it works: At i=1, we check if 3 exists (it does, from i=0), then return [0, 1].
Decision Framework
What do you need from duplicates?
├─ Any valid occurrence → Store last (overwrite)
├─ Earliest occurrence → Store first (check if exists)
├─ How many times → Count (increment)
└─ All positions → Store list (append)Common Mistakes
Mistake 1: Wrong Strategy for Problem
❌ Wrong (storing last when need first):
# First unique character with last occurrence
char_map = {}
for i, char in enumerate(s):
char_map[char] = i # Overwrites!
# Now we have last occurrence, not firstMistake 2: Not Checking Before Overwriting
❌ Wrong (Two Sum):
seen[num] = i
if target - num in seen:
return [seen[target - num], i]✅ Correct:
if target - num in seen:
return [seen[target - num], i]
seen[num] = iMistake 3: Using List When Count Suffices
❌ Overkill:
# Valid anagram with lists
char_indices = defaultdict(list)
for i, char in enumerate(s):
char_indices[char].append(i) # Don't need indices!✅ Simpler:
# Just count
from collections import Counter
return Counter(s) == Counter(t)Quick Reference
| Problem | Strategy | Code |
|---|---|---|
| Two Sum | Last | seen[num] = i |
| First Unique Char | First | if num not in seen: seen[num] = i |
| Valid Anagram | Count | Counter(s) |
| Find All Anagrams | All | indices[key].append(i) |
| Contains Duplicate II | Last | seen[num] = i (update) |
Summary
Handling duplicates correctly is about choosing the right strategy.
The 4 strategies:
- Last occurrence: Overwrite (Two Sum, distance problems)
- First occurrence: Check if exists (first unique, earliest)
- Count: Increment (frequency, anagrams)
- All occurrences: Append to list (find all, intersection)
The decision:
- Need any? → Last
- Need earliest? → First
- Need how many? → Count
- Need all? → List
The Two Sum rule: Check before adding (prevents same-index bug)
Next steps:
- Study common hash map mistakes
- Learn index mapping pattern
- Master the complete hash map guide
Handle duplicates correctly, and edge cases become easy.
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
