Hash Map Patterns in Python
This is the written companion to the video on three essential hash map patterns in Python. All three are collected here so you can copy the code, study it at your own pace, or refer back without scrubbing through the video.
Pattern 1: Complement Lookup
Two Sum — O(n) time, O(n) space
Instead of checking every pair, store each value you've seen and look up whether the complement already exists.
def two_sum(nums, target):
seen = {} # value -> index
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = i
return []
Pattern 2: Grouping by Shared Property
Group Anagrams — O(n · k log k) time, O(n · k) space
Sort each word to produce a canonical key. Words that are anagrams produce the same key and land in the same bucket.
def group_anagrams(strs):
anagram_map = defaultdict(list)
for word in strs:
key = tuple(sorted(word))
anagram_map[key].append(word)
return list(anagram_map.values())
Pattern 3: Grouping by Shared Property (Optimized Key)
Group Anagrams, character frequency — O(n · k) time, O(n · k) space
Skip the sort. Count character frequencies instead and use that count array as the key — it drops the log k factor.
def group_anagrams_optimized(strs):
anagram_map = defaultdict(list)
for word in strs:
count = [0] * 26
for char in word:
count[ord(char) - ord('a')] += 1
anagram_map[tuple(count)].append(word)
return list(anagram_map.values())