Tries — Master Recap and Interview Cheatsheet
Advertisement
Tries Master Cheatsheet
Quick-reference for every trie pattern, template, and decision covered in this series.
Core Operations Complexity
| Operation | Time | Space |
|---|---|---|
| Insert word | O(L) | O(L * 26) array, O(L) hashmap |
| Search word | O(L) | O(1) |
| Prefix check | O(L) | O(1) |
| Word Search II | O(MN3^L) pruned | O(sum of word lengths) |
| Max XOR pair | O(32*n) | O(32*n) |
Standard Trie Template
class TrieNode:
def __init__(self):
self.children = {} # char → TrieNode (or [None]*26 for lowercase)
self.is_end = False # True when a complete word ends at this node
# Optional extras:
# self.count = 0 # words passing through (for prefix count)
# self.word = "" # full word (for Word Search II recovery)
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, word):
node = self.root
for c in word:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.is_end = True
def search(self, word):
node = self.root
for c in word:
if c not in node.children:
return False
node = node.children[c]
return node.is_end # must check is_end for exact match
def starts_with(self, prefix):
node = self.root
for c in prefix:
if c not in node.children:
return False
node = node.children[c]
return True # no is_end check for prefixBinary Trie (XOR) Template
def insert_bit(root, n):
node = root
for bit in range(31, -1, -1):
b = (n >> bit) & 1
if b not in node.children:
node.children[b] = {}
node = node.children[b]
def max_xor_query(root, x):
node = root
xr = 0
for bit in range(31, -1, -1):
b = (x >> bit) & 1
want = 1 - b # prefer opposite bit to maximize XOR
if want in node:
xr = (xr << 1) | 1
node = node[want]
else:
xr <<= 1
node = node[b]
return xrWord Search II Template (Trie + Grid DFS)
def findWords(board, words):
# Build trie with word stored at end nodes
root = TrieNode()
for word in words:
node = root
for c in word:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.word = word # store word at end for O(1) recovery
result = []
rows, cols = len(board), len(board[0])
def dfs(r, c, node):
if not (0 <= r < rows and 0 <= c < cols): return
ch = board[r][c]
if ch == '#' or ch not in node.children: return
next_node = node.children[ch]
if next_node.word:
result.append(next_node.word)
next_node.word = None # avoid duplicates
board[r][c] = '#' # mark visited
for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]:
dfs(r+dr, c+dc, next_node)
board[r][c] = ch # restore
for r in range(rows):
for c in range(cols):
dfs(r, c, root)
return resultDecision Guide
| Need | Use |
|---|---|
| Prefix search | Trie (HashSet cannot prefix-query) |
| Multiple words in grid | Trie + Grid DFS (Word Search II) |
| Autocomplete suggestions | Trie + sorted lists at each node |
| Max/Min XOR | Binary Trie (bit by bit, MSB first) |
| Suffix matching | Reversed Trie |
| Count words with prefix | Trie with count field |
| Combined prefix + suffix | Concatenate "suf#pref" as trie key |
Problem Index
| # | Problem | Key Trick |
|---|---|---|
| 01 | Implement Trie | Basic insert/search/prefix |
| 02 | Design Add Search Words | Wildcard DFS with '.' |
| 03 | Word Search II | Trie pruning in grid DFS |
| 04 | Replace Words | First match = shortest root |
| 05 | Maximum XOR Two Numbers | Binary trie greedy opposite bit |
| 06 | Search Suggestions | Sort + bisect or trie lists |
| 07 | Longest Word in Dictionary | Only traverse is_end nodes |
| 08 | Palindrome Pairs | HashMap prefix/suffix check |
| 09 | Stream of Characters | Reverse trie + active nodes |
| 10 | Prefix and Suffix Search | suf#pref concatenated key |
| 11 | Sum of Prefix Scores | count field at each trie node |
| 12 | Concatenated Words | Word break DP + word set |
| 16 | Max XOR with Element | Offline sort + binary trie |
| 18 | Aho-Corasick | Multi-pattern with failure links |
Key Takeaways
- A trie node has exactly two components:
childrenandis_end— everything else is optional metadata for specific problems. searchchecks both path existence ANDis_end = True;startsWithchecks path existence only — forgettingis_endin search is the most common trie bug.- Binary trie inserts numbers bit by bit from MSB; XOR queries greedily take the opposite bit at each level to maximize XOR.
- Word Search II uses a trie to prune DFS — when the current board path diverges from all trie paths, stop recursing immediately.
- The
countfield at each node enables O(L) prefix count queries without DFS — useful for LC 2185 and LC 2416. - Space: array children ([None]*26) use O(26 * nodes) space regardless of words; dict children use O(actual_children * nodes).
- Every trie interview problem is a variation of five core patterns: basic CRUD, grid DFS, count/delete, binary XOR, or autocomplete.
Advertisement
Related reading
Math and Number Theory — Master Recap and Interview Cheatsheet6 min readString Algorithms — Master Recap and Pattern Cheatsheet6 min readBit Manipulation — Complete Interview Guide for FAANG Engineers7 min readSingle Number — XOR Cancellation Every FAANG Interviewer Loves5 min readSingle Number III — XOR Partition Trick That Splits Two Unique Elements7 min readMissing Number — XOR Cancellation vs Gauss Sum Formula7 min read