208. Implement Trie (Prefix Tree) - Detailed Explanation
Problem statement
Implement the Trie class:
Trie()Initializes the trie object.void insert(String word)Inserts the stringwordinto the trie.boolean search(String word)Returnstrueif the exact stringwordis in the trie (i.e., was previously inserted), orfalseotherwise.boolean startsWith(String prefix)Returnstrueif there is any previously inserted string that starts with the givenprefix, orfalseotherwise.
Examples
Input ["Trie","insert","search","search","startsWith","insert","search"] [[], ["apple"],["apple"],["app"], ["app"], ["app"],["app"]] Output [null, null, true, false, true, null, true] Explanation Trie trie = new Trie(); trie.insert("apple"); trie.search("apple"); // returns true trie.search("app"); // returns false (only prefix "app" exists) trie.startsWith("app"); // returns true trie.insert("app"); trie.search("app"); // returns true
Constraints
1 ≤ word.length, prefix.length ≤ 2000wordandprefixconsist only of lowercase English letters.- At most 3·10⁴ calls in total will be made to
insert,search, andstartsWith.
Approach
This question names its own pattern: the Trie, also called a prefix tree. A trie is a tree in which the path from the root to a node spells a string. Every stored word is therefore a route through the tree rather than a value sitting in a slot, and words that share a prefix share that part of the route. The structure is one of the standard data structures behind the recurring coding interview patterns, and it is the answer whenever an interviewer asks about prefixes rather than whole keys.
A hash set looks tempting here, and it does answer search in O(1) on average. It cannot answer startsWith without inspecting every key it holds. The trie turns that query into a walk of at most m steps, where m is the length of the prefix, which is the whole reason to build one.
Trie node structure
Each node holds:
- An array (or map) of up to 26 child pointers, one for each lowercase letter.
- A boolean flag
isEndindicating whether a word ends at this node.
The isEnd flag is what separates a stored word from a passing prefix. Inserting "apple" creates five nodes and sets isEnd only on the last one. So search("app") reaches a real node and still returns false, because that node is only a waypoint, while startsWith("app") returns true from the same node. Insert "app" later and the flag on that existing node flips to true, with no new nodes allocated.
Operations
insert(word)
- Start at the root node.
- For each character
cinword:- Compute its index
i = c - 'a'. - If
node.children[i]isnull, create a newTrieNode. - Move
node = node.children[i].
- Compute its index
- After the last character, mark
node.isEnd = true.
search(word)
- Traverse exactly as in
insert, but if at any stepnode.children[i]isnull, returnfalse. - After processing all chars, return
node.isEnd.
startsWith(prefix)
- Traverse as in
search, but do not checkisEnd. - If you complete the traversal without hitting
null, returntrue.
All three operations are the same walk over one string, differing only in what they do when a child link is missing and in what they report at the end. Write the walk once as a private helper that returns the node reached or null, then express search and startsWith on top of it. Grokking the Coding Interview builds the class in that order in its Implement Trie lesson, which is where the problem and the rest of the trie pattern are taught.
Complexity analysis
- Time: O(m) per operation (m = length of word or prefix).
- Space: In the worst case, O(N·L) for storing all inserted words (N words of average length L), since each character may create a new node.
Python code
Java code
Common mistakes
- Forgetting to mark
isEndon insert, causingsearchto return false for inserted words. - Using a map per node instead of a fixed-size array, which increases constant factors.
- In
startsWith, accidentally requiringisEndto be true. - Allocating the 26-slot child array in every node before you need it, which wastes memory on sparse branches. Allocate a child only when a character first needs it.
Edge cases
- Inserting or searching the same word multiple times.
- Searching for a prefix that is exactly an inserted word.
- Very long words near the maximum length.
- A
searchorstartsWithcall on an empty trie, which must returnfalseon the first missing child link rather than fail.
Related problems
Prefix queries scale up quickly once the class exists. In Counting Words With a Given Prefix you report the number of matches instead of a yes or no, which a counter stored per node answers in the same walk. Then Word Search II pairs the trie with depth-first search and uses it to prune dead branches of the grid. For a question built directly on this class, try Search Suggestions System, which returns the first three matching products for every prefix of a search term. All three reward the same groundwork, and Grokking the Coding Interview collects them into one chapter.

GET YOUR FREE
Coding Questions Catalog

$99

$197

$72