Common Map Patterns
Pattern 1: Frequency Counter
Track how often each element appears.
def most_frequent(nums):
freq = {}
max_count = 0
result = None
for num in nums:
freq[num] = freq.get(num, 0) + 1
if freq[num] > max_count:
max_count = freq[num]
result = num
return result
nums = [1, 3, 2, 3, 3, 1, 3]
print(most_frequent(nums)) # 3
With Counter
from collections import Counter
def top_k_frequent(nums, k):
freq = Counter(nums)
return [num for num, count in freq.most_common(k)]
nums = [1, 1, 1, 2, 2, 3]
print(top_k_frequent(nums, 2)) # [1, 2]
Pattern 2: Index Mapping
Map values to their positions.
def two_sum(nums, target):
"""Find indices of two numbers that sum to target"""
seen = {} # num -> index
for i, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], i]
seen[num] = i
return []
nums = [2, 7, 11, 15]
print(two_sum(nums, 9)) # [0, 1]
Pattern 3: Multiple Values per Key
Group related items together.
from collections import defaultdict
def group_shifted_strings(strings):
"""Group strings that are shifts of each other"""
groups = defaultdict(list)
for s in strings:
# Create key based on shift pattern
key = tuple((ord(s[i+1]) - ord(s[i])) % 26
for i in range(len(s) - 1))
groups[key].append(s)
return list(groups.values())
strings = ["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"]
print(group_shifted_strings(strings))
# [['abc', 'bcd', 'xyz'], ['acef'], ['az', 'ba'], ['a', 'z']]
Pattern 4: Complement Lookup
Find pairs that satisfy a condition.
def find_pairs(nums, k):
"""Count pairs with difference k"""
num_set = set(nums)
count = 0
for num in num_set:
if num + k in num_set:
count += 1
return count
nums = [1, 3, 1, 5, 4]
print(find_pairs(nums, 2)) # 3: (1,3), (3,5), (3,1)
Pattern 5: Running Sum/Product
Track cumulative values for subarray problems.
def subarray_sum(nums, k):
"""Count subarrays with sum equal to k"""
prefix_sums = {0: 1} # sum -> count
current_sum = 0
count = 0
for num in nums:
current_sum += num
# Check if (current_sum - k) exists
if current_sum - k in prefix_sums:
count += prefix_sums[current_sum - k]
# Update prefix sum count
prefix_sums[current_sum] = prefix_sums.get(current_sum, 0) + 1
return count
nums = [1, 1, 1]
print(subarray_sum(nums, 2)) # 2: [1,1] appears twice
Pattern 6: State Tracking
Remember what you've seen and make decisions.
def can_construct(ransom_note, magazine):
"""Can we build ransom note from magazine letters?"""
available = {}
# Count available letters
for char in magazine:
available[char] = available.get(char, 0) + 1
# Try to use letters
for char in ransom_note:
if available.get(char, 0) == 0:
return False
available[char] -= 1
return True
print(can_construct("aa", "aab")) # True
print(can_construct("aa", "ab")) # False
Pattern 7: Coordinate/Position Mapping
Map coordinates to values for grid problems.
def is_path_crossing(path):
"""Does path cross itself?"""
x, y = 0, 0
visited = {(0, 0)}
moves = {'N': (0, 1), 'S': (0, -1),
'E': (1, 0), 'W': (-1, 0)}
for direction in path:
dx, dy = moves[direction]
x, y = x + dx, y + dy
if (x, y) in visited:
return True
visited.add((x, y))
return False
print(is_path_crossing("NES")) # False
print(is_path_crossing("NESWW")) # True
Pattern 8: First Unique Element
Track order and frequency simultaneously.
def first_unique_char(s):
"""Find first non-repeating character"""
freq = {}
# Count frequencies
for char in s:
freq[char] = freq.get(char, 0) + 1
# Find first with frequency 1
for i, char in enumerate(s):
if freq[char] == 1:
return i
return -1
print(first_unique_char("leetcode")) # 0 ('l')
print(first_unique_char("loveleetcode")) # 2 ('v')
Pattern 9: Longest/Shortest Sequence
Track boundaries or lengths.
def longest_substring_without_repeating(s):
"""Find length of longest substring without repeating chars"""
char_index = {}
max_length = 0
start = 0
for end, char in enumerate(s):
# If char seen and in current window
if char in char_index and char_index[char] >= start:
start = char_index[char] + 1
char_index[char] = end
max_length = max(max_length, end - start + 1)
return max_length
print(longest_substring_without_repeating("abcabcbb")) # 3 ("abc")
print(longest_substring_without_repeating("bbbbb")) # 1 ("b")
Pattern 10: Graph as Adjacency Map
Represent graph relationships.
def build_graph(edges):
"""Build adjacency list from edges"""
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u) # For undirected
return graph
edges = [(1, 2), (1, 3), (2, 4)]
graph = build_graph(edges)
print(dict(graph))
# {1: [2, 3], 2: [1, 4], 3: [1], 4: [2]}
Summary of Patterns
- Frequency Counter: Count occurrences
- Index Mapping: Remember positions
- Grouping: Collect related items
- Complement Lookup: Find matching pairs
- Prefix Sums: Track running totals
- State Tracking: Remember what you've seen
- Coordinate Mapping: Position-based storage
- Order + Frequency: Track both simultaneously
- Window Tracking: Sliding window problems
- Graph Representation: Adjacency lists