Core idea: A trie turns a set of words into a tree of characters. Walking one edge per letter, every word becomes a path from the root, and words that share a prefix share that prefix's path. A single boolean flag (
is_end) on a node says "a word ends right here." That layout makes "does any word start withapp?" cost only the length ofapp— never the size of the dictionary.
Problem, rephrased
You're building the in-memory index behind a search box. Words stream in one at a time (insert), and the box must answer two very different questions instantly:
- Exact lookup — "is
applea word I've stored?" (search) - Prefix lookup — "is there any stored word that begins with
app?" (startsWith)
Build a structure Trie supporting:
insert(word)— addwordto the index.search(word)— returnTrueonly if the exactwordwas inserted earlier.startsWith(prefix)— returnTrueif some stored word hasprefixas a leading substring (the prefix itself need not be a stored word).
This is LeetCode 208. Inputs are non-empty strings of lowercase letters a–z.
Here's a transcript on a fresh trie, top to bottom:
| Call | Returns | Why |
|---|---|---|
insert("apple") |
— | store the word apple |
search("apple") |
True |
exact word apple exists |
search("app") |
False |
the path a→p→p exists, but no word ends there |
startsWith("app") |
True |
apple begins with app |
insert("app") |
— | now mark the node after a→p→p as a word-end |
search("app") |
True |
the same path now ends a real word |
The crux is row 3 vs. row 6: the path app existed all along, but it only counts as a stored word once is_end is set on its final node. That distinction — path exists vs. word ends here — is the whole trie in one sentence.
Sign in to continue reading
The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.
Sign in to read the full lesson