By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
"This single data structure appears in 1 out of every 3 onsite interviews—master it, and you’ll instantly stand out as a candidate who understands efficient string search, autocomplete, and dictionary lookups at scale."
Before diving into Tries, ensure you understand: 1. Tree Data Structures (Nodes, children, traversal) 2. Hash Maps / Dictionaries (Key-value lookups, O(1) average case) 3. Recursion vs. Iteration (DFS traversal, backtracking)
class TrieNode: children = {}; is_end = False
is_end
True
Follow these steps every time you implement a Trie:
TrieNode
children
is_end: A boolean flag marking the end of a word.
Initialize the Trie
Create a root node (TrieNode()).
TrieNode()
Implement insert(word)
insert(word)
word
Mark the last node as is_end = True.
is_end = True
Implement search(word) (Exact Match)
search(word)
False
Return True only if is_end is True.
Implement startsWith(prefix)
startsWith(prefix)
Same as search, but return True if the path exists (don’t check is_end).
search
Handle Edge Cases
""
Case sensitivity (convert to lowercase if needed).
Optimize for Follow-ups
Problem: Design a Trie with insert, search, and startsWith methods.
insert
startsWith
class TrieNode: def __init__(self): self.children = {} # char -> TrieNode self.is_end = False class Trie: def __init__(self): self.root = TrieNode() def insert(self, word: str) -> None: node = self.root for char in word: if char not in node.children: node.children[char] = TrieNode() node = node.children[char] node.is_end = True def search(self, word: str) -> bool: node = self.root for char in word: if char not in node.children: return False node = node.children[char] return node.is_end def startsWith(self, prefix: str) -> bool: node = self.root for char in prefix: if char not in node.children: return False node = node.children[char] return True
Why this works: - Insertion builds the Trie incrementally, ensuring all prefixes are stored. - Search leverages the Trie’s structure to check for exact matches in O(L) time. - startsWith reuses the same traversal but ignores is_end.
Problem: Given an m x n board and a list of words, return all words on the board (each word must be formed by adjacent letters, no reuse).
m x n
class TrieNode: def __init__(self): self.children = {} self.word = None # Store the word at the end node class Solution: def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: # Build Trie root = TrieNode() for word in words: node = root for char in word: if char not in node.children: node.children[char] = TrieNode() node = node.children[char] node.word = word # Mark end of word # DFS on board res = [] m, n = len(board), len(board[0]) def dfs(i, j, node): char = board[i][j] if char not in node.children: return next_node = node.children[char] if next_node.word: res.append(next_node.word) next_node.word = None # Avoid duplicates # Mark as visited board[i][j] = "#" for di, dj in [(-1,0), (1,0), (0,-1), (0,1)]: ni, nj = i + di, j + dj if 0 <= ni < m and 0 <= nj < n and board[ni][nj] != "#": dfs(ni, nj, next_node) board[i][j] = char # Backtrack for i in range(m): for j in range(n): dfs(i, j, root) return res
Why this works: - Trie efficiently checks prefixes, reducing redundant searches. - DFS + Backtracking explores all possible paths while avoiding revisits. - Early Termination (next_node.word = None) prevents duplicate results.
next_node.word = None
Problem: Design a data structure that supports: - addWord(word) - search(word) (where . matches any character)
addWord(word)
.
addWord
class TrieNode: def __init__(self): self.children = {} self.is_end = False class WordDictionary: def __init__(self): self.root = TrieNode() def addWord(self, word: str) -> None: node = self.root for char in word: if char not in node.children: node.children[char] = TrieNode() node = node.children[char] node.is_end = True def search(self, word: str) -> bool: def dfs(node, i): if i == len(word): return node.is_end char = word[i] if char == ".": for child in node.children.values(): if dfs(child, i + 1): return True return False else: if char not in node.children: return False return dfs(node.children[char], i + 1) return dfs(self.root, 0)
Why this works: - Trie efficiently stores words for exact matches. - DFS for Wildcards explores all possible paths when . is encountered. - Early Termination returns as soon as a match is found.
search("")
"Alright, let’s lock this in. A Trie is just a tree of characters where each path represents a word. Here’s the playbook:
You’ve got this. Now go implement it—fast, clean, and without bugs. Good luck!
This guide is 100% interview-ready—use it to dominate your next Trie problem! ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.