🧱
Core Data Structures
O(1) membership · frequency counting · dedup
06. Hashing — dict, set, Counter
Hash maps and sets give you O(1) average-case lookups. They turn many O(n²) brute-force problems into one-pass solutions. Master dict, set, defaultdict, and Counter.
dictsetCounterhash
Duration
⏱ ~1 hour
Level
📊 Beginner
Prerequisite
🎯 Lecture 3
OUTCOME
Spot when a hash structure changes the complexity class of your solution.
What you'll learn
- 1Use dict for O(1) key/value lookup
- 2Use set for O(1) membership and dedup
- 3Use defaultdict and Counter for clean code
Overview
If your solution has a nested loop that re-scans a list, you can usually replace the inner scan with a hash lookup and drop a factor of N. This is the most common O(n²) → O(n) optimization.
Core Concepts
1. dict basics
python
scores = {'alice': 90, 'bob': 82}
scores['alice'] # 90
scores['carol'] = 78 # insert
'alice' in scores # True (O(1))
scores.get('dave', 0) # default if missing — never raises
del scores['bob']
for k, v in scores.items(): ... # iterate pairs2. set
python
seen = set()
seen.add(3)
5 in seen # O(1)
A, B = {1,2,3}, {2,3,4}
A | B # union {1,2,3,4}
A & B # intersect {2,3}
A - B # difference {1}
A ^ B # symmetric diff {1,4}3. defaultdict — no KeyError
python
from collections import defaultdict
# Group items
groups = defaultdict(list)
for word in words:
groups[len(word)].append(word)
# Count items
count = defaultdict(int)
for c in 'banana':
count[c] += 14. Counter — built-in counting
python
from collections import Counter
c = Counter('banana')
c.most_common(2) # [('a', 3), ('n', 2)]
c['a'] # 3
c['z'] # 0 (no KeyError)
# Counter algebra
Counter('aab') + Counter('abc') # {'a':3, 'b':2, 'c':1}Examples
Example 1 — src/01_dict_basics.py
CRUD on a dict + iteration patterns.
Example 2 — src/02_set_dedup.py
Deduplicate a list with set() and preserve original order with dict.fromkeys.
Example 3 — src/03_two_sum.py
The classic two-sum problem reduced from O(n²) to O(n) using a dict.
Example 4 — src/04_counter.py
Word/character frequency with collections.Counter.
Common Mistakes
- Using `if k in dict.keys():` — that's still O(n) on some Python versions. Just write `if k in dict:`.
- Using a list when you mean a set. `if x in [1,2,3,...big...]:` is O(n).
- Forgetting unhashable types: list and dict can't be dict keys. Use tuple instead.
- Mutating a dict while iterating it. Iterate over list(d) or d.copy() instead.
Recap
- dict / set are your default tools for O(1) lookup.
- defaultdict and Counter eliminate boilerplate.
- Hashing-based optimization is the most common O(n²) → O(n) trick.
Try It
- BOJ 1764 (Listen & See) — set intersection.
- BOJ 1620 (Pokémon Master) — bidirectional dict.
Example code / lecture materials
All lecture materials and example code are openly available on GitHub.
View on GitHub ↗