Tries
A tree of letters where every shared prefix is stored once — prefix questions in O(length of the word).
▶ guided lesson⚡ 1-minute summary↻ 15 recall cards
before this: Tree Recursion · Hashing · Recursion
01 · why it exists
Why this exists, and the weight it carries
since1959–60
Trie (prefix tree)
René de la Briandais; Edward Fredkin (who named it)
In March 1959 René de la Briandais presented "File searching using variable length keys": store keys letter by letter in a tree, so a lookup reads one letter per level. In September 1960 Edward Fredkin independently described the same idea in "Trie Memory" (Communications of the ACM) and coined the name from re-trie-val. Fredkin meant it to be said like "tree"; many people say "try" to keep the two apart.
the problem it solvedLooking up keys of different lengths — words, codes — in time that depends on the key's length, not on how many keys are stored.
its jobs today
- Autocomplete and typeahead: walk to the typed prefix, then read precomputed suggestions from that node.
- Spell checkers and word games: explore only the letter paths that real words use.
- Prefix routing and dictionaries keyed by strings or bits, often as compressed (radix) tries.
the weight it carries
Illustrative: 10 lakh (1,000,000) stored names and the user has typed "pri". Trie: 3 steps to the prefix node, whatever the number of names. HashSet<String>: a prefix has no bucket, so up to 1,000,000 startsWith checks. Sorted array or TreeSet: ⌈log₂ 1,000,000⌉ = 20 string comparisons to find the first match.
without it
Every keystroke in a search box would rescan the whole list, or need a sorted copy plus a binary search per prefix.
when · why · how
- when
- Many prefix questions over one set of strings: startsWith, autocomplete, shortest root, many words on one board, wildcard search.
- why
- Each query costs O(L) for an L-letter prefix, independent of N. The price is memory: up to one node per stored letter, 26 child slots each with
Node[26]. - how
class Node { Node[] children = new Node[26]; boolean isEnd; }— index withch - 'a'; switch toHashMap<Character, Node>for big or unknown alphabets.
since1968
Binary trie (bitwise trie)
Donald R. Morrison (PATRICIA)
Fredkin's tries branch on letters; the same idea works on the bits of a key. In 1968 Donald R. Morrison published PATRICIA ("Practical Algorithm To Retrieve Information Coded in Alphanumeric") in the Journal of the ACM. NIST describes a Patricia tree as a trie in which every only child is merged into its parent, and a radix tree as a binary Patricia tree. The max-XOR trie in this chapter is the plain, uncompressed version: 31 levels, one per bit.
the problem it solvedStoring and searching keys bit by bit, so lookups cost the key's length in bits and runs of single-child nodes need not be stored.
its jobs today
- Maximum-XOR queries: pick the opposite bit at every level, highest bit first.
- IP routing: an address is matched against route prefixes bit by bit; the Linux kernel's routing table (fib_trie) is a compressed trie of that kind.
the weight it carries
Illustrative: LC 421's limit, n = 2·10⁵ numbers. All pairs: n(n − 1)/2 = 19,999,900,000 ≈ 2·10¹⁰ XORs. Binary trie: 31 steps to insert + 31 to query per number = 62 × 200,000 = 12,400,000 steps — about 1,600× fewer.
without it
Max-XOR and other "closest by bits" questions fall back to checking every pair: O(n²).
when · why · how
- when
- XOR maximisation over pairs or queries, or matching keys bit by bit (longest prefix of an address).
- why
- Each number is a fixed 31-bit path, so insert and query are O(31) = O(1) per number. Greedy works because bit b outweighs all lower bits together (2ᵇ > 2ᵇ − 1).
- how
Node[] child = new Node[2]; read bit b with(num >> b) & 1for b = 30 down to 0.
since?
Trie-guided backtracking (many words at once)
No single inventor: it is a trie's prefix check used to cut a backtracking search short — a standard combination in word-game solvers and in problems like Word Search II.
its jobs today
- Word games and puzzle solvers: find every dictionary word on a letter board in one search.
- Spell suggestions: walk the dictionary trie while allowing a few edits, and drop any branch with no word left below it.
the weight it carries
Illustrative: LC 212's limits — a 12 × 12 board and 30,000 words. Word Search I per word starts 30,000 × 144 = 4,320,000 searches. With a trie: 144 searches in total, one per start cell, each cut off as soon as its prefix leaves the trie.
without it
Multi-word search would repeat the same board exploration once for every word.
when · why · how
- when
- Many patterns against one board or text, where most paths die after a few letters.
- why
- Shared prefixes are explored once for all words, and a missing child prunes the branch for every word together. The worst case is still exponential in word length; real boards collapse fast.
- how
- Store
String wordon end nodes, mark visited cells with '#', restore them after the DFS, setnode.word = nullonce found, and trim leaves that hold no word.
02 · plain english
The idea in 30 seconds
A trie (prefix tree) stores words letter by letter: each edge is a letter, each root-to-node path spells a prefix.
Words that share a beginning share the same path, so "car", "card" and "care" reuse the nodes c → a → r.
Any lookup walks one node per letter: O(L) for a word of length L, no matter if you stored 10 words or 10 million.
picture this
Your phone's contact search: type "Pr" and the list instantly narrows to Pradeep, Pranav and Priya. Nothing scans every contact — each letter you type is one step down a path those names share.
03 · remember
What you must know
- The root is empty. A node is reached by a path of letters; the node itself stands for that prefix.
- An end-of-word flag (
isEnd) is essential: without it you can't tell the stored word "app" from the mere prefix of "apple". search(word)= the path exists andisEndis true.startsWith(prefix)= the path exists. Same walk, different final check.- Children as
Node[26]= fastest and simplest for lowercase a–z, but every node pays for 26 slots.HashMap<Character, Node>= only the letters that exist, any alphabet, slower constant. - Add counters for free superpowers:
pass(words through this node) answers "how many words start with p?" in O(L), and makes delete easy. - Autocomplete = walk to the prefix node, then DFS its subtree. Visiting children a→z returns results already sorted. For top-k suggestions, store the k best words on each node at insert time.
- A wildcard
.turns search into a DFS that branches only at the dots; normal letters still follow one child. - Tries aren't only for letters: a binary trie stores numbers bit by bit (high bit first) and answers max-XOR queries greedily.
- Many words + one grid (Word Search II) → put the words in a trie and let it prune the DFS: stop as soon as no word has the current prefix.
- When the match runs backwards, insert the words reversed — Palindrome Pairs reads one word forwards down a trie of reversed words.
04 · see it
Play with it in 3D
Press Space to play, ←/→ to step, drag to move, ? for all shortcuts. Try your own input.
Insert words — shared prefixes reuse nodes
New letters grow new branches; known prefixes are walked, not copied. Boxes mark where a word ends.
search(word) vs startsWith(prefix)
Both walk the same path. Only search also demands the end-of-word box at the last letter.
Counting trie — count prefixes, erase, prune
Each node shows how many words pass through it. Erase decrements; when a count hits 0 the whole branch is cut.
Autocomplete — DFS below the prefix node
Everything outside the prefix's subtree stays grey: it is never touched.
Wildcard search — branch only at the dots
A letter follows exactly one child; a '.' tries the children one by one. Grey nodes are branches that failed.
Search suggestions — a top-3 list on every node
Products go in sorted, so the first 3 words through a node are its 3 smallest. Typing is then one step per letter.
Word Search II — a trie steering a grid DFS
One DFS hunts all words at once. Red = pruned (no word continues this way). Finished branches are trimmed from the trie.
Binary trie — maximum XOR, one bit at a time
For every bit, try to go the opposite way: a 1 in a higher bit is worth more than all lower bits together.
05 · cost
Time & space, explained
| Time | Extra space | why | |
|---|---|---|---|
| insert(word) | O(L) | O(L) worst | One step per letter; at most L new nodes when no prefix is shared. |
| search(word) | O(L) | O(1) | Walk at most L edges, then check one flag. The number of stored words never appears. |
| startsWith(prefix) | O(L) | O(1) | The same walk as search, without the final flag check. |
| search with k wildcards | O(Σᵏ · L) worst | O(L) | Each '.' may fan out to Σ = 26 children; letters never branch. Never more than the nodes in the trie. |
| countWordsStartingWith(prefix) | O(L) | O(1) | With a pass counter on every node, the answer is stored at the prefix node. |
| erase(word) (counting trie) | O(L) | O(1) | Walk once, decrement counters, cut the branch where a counter hits 0. |
| autocomplete(prefix) | O(L + K) | O(depth) | L to reach the prefix node, then K = nodes in its subtree (plus output); recursion depth = longest word. |
| Build from N words | O(S) | O(S·Σ) array / O(S) map | At most S + 1 nodes. Each array node always holds Σ = 26 references, even if empty. |
| contains(word) | any word starts with p? | Memory | why | |
|---|---|---|---|---|
| HashSet<String> | O(L) average | O(N·L) | O(S) | Hashing a word costs O(L), but a prefix has no hash bucket — you must scan every word. |
| TreeSet<String> / sorted array | O(L log N) | O(L log N) | O(S) | ceiling(p) finds the first word ≥ p in log N comparisons, each up to L chars. |
| Trie with Node[26] | O(L) | O(L) | O(S·26) | Fastest walk: array index per letter. Pays 26 slots per node, used or not. |
| Trie with HashMap children | O(L) average | O(L) average | O(S), bigger constant | Only existing letters are stored, but each map entry has object overhead (boxed Character, entry, table). |
06 · java
Raw vs Collections Framework
Children: Node[26] array vs HashMap
class Trie { private static class Node { Node[] children = new Node[26]; // one slot per letter 'a'..'z' boolean isEnd; // true if a word ends exactly here } private final Node root = new Node(); public void insert(String word) { Node cur = root; for (char ch : word.toCharArray()) { int i = ch - 'a'; if (cur.children[i] == null) cur.children[i] = new Node(); cur = cur.children[i]; } cur.isEnd = true; } public boolean search(String word) { Node node = walk(word); return node != null && node.isEnd; } public boolean startsWith(String prefix) { return walk(prefix) != null; } /** Follows s letter by letter; null as soon as a letter is missing. */ private Node walk(String s) { Node cur = root; for (char ch : s.toCharArray()) { cur = cur.children[ch - 'a']; if (cur == null) return null; } return cur; }}class MapTrie { private static class Node { Map<Character, Node> children = new HashMap<>(); // only letters that exist boolean isEnd; } private final Node root = new Node(); public void insert(String word) { Node cur = root; for (char ch : word.toCharArray()) { cur = cur.children.computeIfAbsent(ch, k -> new Node()); } cur.isEnd = true; } public boolean search(String word) { Node node = walk(word); return node != null && node.isEnd; } public boolean startsWith(String prefix) { return walk(prefix) != null; } private Node walk(String s) { Node cur = root; for (char ch : s.toCharArray()) { cur = cur.children.get(ch); if (cur == null) return null; } return cur; }}ch - 'a'turns a letter into an index 0..25 — no hashing, no boxing. This is the interview default when the input is lowercase a–z.computeIfAbsent(ch, k -> new Node())gets the child or creates it in one call — the map version of "if null, create".- Use the map version for Unicode, mixed case, digits, or very sparse tries (most nodes have one or two children).
- Want children in sorted order with a map? Use
TreeMap<Character, Node>— O(log Σ) per step, but iteration is alphabetical. - Java has no built-in trie class. You will always write the ~25 lines yourself — practise until it takes 3 minutes.
Counting trie — prefix counts and delete
class CountingTrie { private static class Node { Node[] children = new Node[26]; int pass; // how many stored words go through this node int end; // how many stored words end exactly here } private final Node root = new Node(); void insert(String word) { Node cur = root; cur.pass++; for (char ch : word.toCharArray()) { int i = ch - 'a'; if (cur.children[i] == null) cur.children[i] = new Node(); cur = cur.children[i]; cur.pass++; } cur.end++; } int countWordsEqualTo(String word) { Node node = walk(word); return node == null ? 0 : node.end; } int countWordsStartingWith(String prefix) { Node node = walk(prefix); return node == null ? 0 : node.pass; } /** Removes one copy of word (if stored) and frees branches no word uses any more. */ void erase(String word) { if (countWordsEqualTo(word) == 0) return; Node cur = root; cur.pass--; for (char ch : word.toCharArray()) { int i = ch - 'a'; Node next = cur.children[i]; if (--next.pass == 0) { cur.children[i] = null; return; // nothing below was used by any other word } cur = next; } cur.end--; } private Node walk(String s) { Node cur = root; for (char ch : s.toCharArray()) { cur = cur.children[ch - 'a']; if (cur == null) return null; } return cur; }}passanswers "how many words start with p" without visiting the subtree;endsupports duplicates.- Delete is the classic trap: don't just clear
isEnd— counters tell you exactly which nodes no longer serve any word, so you can cut them. - Cutting one reference (
children[i] = null) frees the whole branch; the garbage collector does the rest.
Autocomplete — collect words under a prefix
class Autocomplete { private static class Node { Node[] children = new Node[26]; boolean isEnd; } private final Node root = new Node(); void insert(String word) { Node cur = root; for (char ch : word.toCharArray()) { int i = ch - 'a'; if (cur.children[i] == null) cur.children[i] = new Node(); cur = cur.children[i]; } cur.isEnd = true; } /** Every stored word that starts with prefix, in alphabetical order. */ List<String> complete(String prefix) { List<String> out = new ArrayList<>(); Node cur = root; for (char ch : prefix.toCharArray()) { cur = cur.children[ch - 'a']; if (cur == null) return out; } collect(cur, new StringBuilder(prefix), out); return out; } /** DFS below the prefix node. Visiting 'a'..'z' in order gives sorted output for free. */ private void collect(Node node, StringBuilder path, List<String> out) { if (node.isEnd) out.add(path.toString()); for (int i = 0; i < 26; i++) { if (node.children[i] == null) continue; path.append((char) ('a' + i)); collect(node.children[i], path, out); path.deleteCharAt(path.length() - 1); } }}- One shared
StringBuilder: append before going down,deleteCharAtafter coming back — the backtracking pattern. - Looping
i = 0..25visits children alphabetically, so results come out sorted with no extra sort. - For "top 3 suggestions" store the best 3 words on every node at insert time (see LC 1268) — queries become O(L).
| call | does | cost |
|---|---|---|
new Node[26] | Child slots for 'a'..'z'; all start as null | O(26) to allocate |
ch - 'a' | Letter → index 0..25 (char arithmetic) | O(1) |
(char) ('a' + i) | Index → letter, when rebuilding words in a DFS | O(1) |
map.computeIfAbsent(ch, k -> new Node()) | Get the child, creating it if missing | O(1) average |
map.get(ch) | Child or null | O(1) average |
new TreeMap<Character, Node>() | Children kept in sorted order | O(log Σ) per step |
sb.append(c) / sb.deleteCharAt(sb.length() - 1) | Grow / shrink the current path while backtracking | O(1) amortized |
new StringBuilder(w).reverse().toString() | A word reversed (Palindrome Pairs) | O(L) |
treeSet.ceiling(prefix) | First stored string ≥ prefix — a trie-free prefix check | O(L log N) |
(num >> b) & 1 | Bit b of num (binary trie) | O(1) |
Many prefix queries on a fixed set of words
→ Trie (Node[26])
Every query is O(L), independent of N.
Only exact lookups ("is this word in the set?")
→ HashSet<String>
Simpler and less memory; a trie buys you nothing here.
Unicode / large or unknown alphabet
→ Trie with HashMap children
A 65,536-slot array per node would be absurd.
A few prefix queries, memory matters
→ Sorted array / TreeSet + binary search
No per-node overhead; O(L log N) per query is often fine.
Max XOR / bitwise "closest" numbers
→ Binary trie (2 children)
Greedy bit-by-bit choice from the highest bit.
Find many words in a grid or text
→ Trie + DFS (or Aho–Corasick for text)
One traversal serves all words and prunes dead prefixes.
07 · recognise
Spot the pattern
"prefix", "starts with", "autocomplete", "suggestions", "typeahead"
Trie — walk to the prefix node
Search many words at once in a grid or a string
Put all words in a trie, run one DFS that follows the trie
Wildcards like . matching any letter
Trie + DFS that branches only at the wildcard
Replace words by their shortest root / dictionary prefix
Trie: stop at the first end-of-word node on the walk
Maximize XOR of pairs, or XOR queries against a set
Binary trie, highest bit first, greedily take the opposite bit
"Built one character at a time", "every prefix is also a word"
Trie DFS that only enters end-of-word nodes
Count words with a given prefix, with inserts and deletes
Counting trie (pass / end counters)
Two strings joined must form a palindrome, or match end-to-start
Trie (or HashMap) of the words reversed
08 · traps & tricks
Mistakes to avoid, tricks to use
traps
- Forgetting
isEnd: thensearch("app")returns true after inserting only "apple". - Returning
truefromsearchjust because the walk finished — the final node must also be an end of word. - Deleting by clearing
isEndbut leaving dead branches:startsWithstill says yes for a prefix no word has. - Using
Node[26]when the input has uppercase, digits or spaces —ch - 'a'goes negative or past 25 →ArrayIndexOutOfBoundsException. - Wildcard search: returning the result of the first child at a '.', instead of trying the next child when it fails.
- Word Search II: forgetting to un-mark the cell after the DFS, or reporting the same word twice (clear the stored word once found).
- Binary trie: walking bits from low to high. Greedy only works from the highest bit down.
- Building the whole trie when you only need one exact lookup — a
HashSetis simpler and lighter.
tricks
- Write the node class first and say it out loud: "children plus an end flag". Everything else follows.
- Factor out a
walk(s)helper that returns the node or null;searchandstartsWithbecome one line each. - In word problems, store the whole word on its end node (
String word) instead of a boolean — no need to rebuild it from the path. - Mention the memory trade-off unprompted: "26 references per node; with a map I'd only pay for existing letters." It signals depth.
- If the interviewer asks for top-k suggestions, keep a small sorted list on each node at insert time instead of DFS at query time.
- Chalo, dry-run karte hain — with 3 words that share a prefix ("car", "card", "cat"). It exposes most trie bugs.
09 · why & how
Questions you might be too shy to ask
Where is the letter actually stored? And why is the root empty?
With Node[26], the letter isn't stored as a value at all — it is the slot number.
children[2] != null means "there is an edge for 'c' here".
The root stands for the empty prefix "", so words starting with different letters can all hang under one starting point.
So the path root → c → a → t spells "cat"; each node is "the prefix so far".
Why does ch - 'a' give me a number?
In Java a char is a small number underneath: 'a' is 97, 'b' is 98, 'c' is 99.
Subtracting two chars gives an int, so 'c' - 'a' is 2 — the slot for 'c'.
Going back: (char) ('a' + 2) is 'c'. This only works because 'a'..'z' are consecutive numbers.
Why is a trie lookup O(L) and not O(log N) like a balanced tree?
A BST compares whole words at each node, and it has log N levels. A trie consumes one letter per level, and the number of levels is the length of the word. Ten words or ten million — a 5-letter lookup takes 5 steps.
Why is the Node class static?
A nested class without static secretly keeps a reference to the outer Trie object inside every node.
A trie can have lakhs of nodes, so that's wasted memory for nothing — a node never needs the outer object.
private static class Node is a plain small class that just lives inside Trie. Use it for TreeNode-style helpers too.
Isn't a HashSet also O(L)? Why bother with a trie?
For exact lookups, yes — a HashSet is usually the better choice. The trie wins as soon as prefixes matter: a HashSet has no way to answer "does any word start with 'ap'?" without scanning all N words.
Can't I just put every prefix of every word in a HashSet?
You can — startsWith becomes one O(L) lookup. But "apple" alone adds 5 strings (a, ap, app, appl, apple): 15 characters for a 5-letter word.
That is O(L²) time and memory per word, where a trie needs O(L).
And the set still can't list the words under a prefix (autocomplete). Fine for small inputs; say the trade-off.
What happens if I insert the same word twice?
With a boolean isEnd, nothing changes: the walk finds every node already there and sets a flag that is already true.
If duplicates must be counted, use an int end counter and do end++ instead (the counting trie in the Java section).
How much memory does a trie really use?
At most S + 1 nodes for S total letters (fewer when prefixes are shared). With Node[26], each node holds 26 references (~104–208 bytes in Java on top of the object header), even if only one is used. For sparse data that is wasteful — use a HashMap per node, or a compressed (radix) trie that merges single-child chains.
Array or HashMap for children in an interview?
If the problem says lowercase English letters, use Node[26] — it's shorter, faster and expected. Switch to a map for big or unknown alphabets, and say why.
How do I delete a word correctly?
Keep a pass counter on each node (and end for words ending there). Walk the word decrementing pass; if you reach the last node, decrement its end too. The first node whose counter hits 0 is used by no other word, so cut the link to it and stop — everything below disappears with it. Without counters, use a recursive delete that removes a child only if it has no children and isn't an end of word.
Why does Word Search II need a trie when Word Search I didn't?
Word Search I looks for one word. With W words, running Word Search I W times repeats the same board exploration W times. A trie of all words lets one DFS follow every word's prefix at once and stop the moment no word continues that way.
What is a binary trie, and why does greedy work for maximum XOR?
It stores each number as a path of bits, highest bit first. To maximize a ^ b, you want bit 30 of the result to be 1 if at all possible, because 2³⁰ is bigger than all lower bits added together (2³⁰ − 1). So at each level take the opposite bit if that child exists — a local choice that can never be beaten later.
Max XOR: why start at bit 30 and not bit 31?
The numbers are non-negative ints, so they are below 2³¹. Bit 31 is the sign bit, and it is 0 for all of them.
Two zeros XOR to 0, so that level would never help. Bit 30 is the highest bit that can actually differ.
If negative numbers were allowed, you would need bit 31 too — and to treat it with care.
Palindrome Pairs feels impossible. Where do I start?
With the condition, not the code. Say words[i] + words[j] is a palindrome and words[i] is the longer one. Then the beginning of words[i] is words[j] backwards, and the leftover part of words[i] reads the same both ways. (When words[j] is longer, flip it: the end of words[j] is words[i] backwards.) So store every word reversed (in a HashMap or a trie) and look up pieces of words[i] in it. Brute force first, then this — interviewers mostly want to see that reasoning.
10 · practice
Interview problems
Every problem has brute → better → optimal solutions in Java, with complexity and a dry run.
- #208
- #211
- #212
- #648Replace WordsMediumByteDance / TikTokMicrosoftGoogle
- #1268
- #421Maximum XOR of Two Numbers in an ArrayMediumBloomberg
- #720Longest Word in DictionaryMediumMicrosoftAmazon
- #336Palindrome PairsHardAirbnbGoogleAmazon
Also practise this here
Each problem has one home page in the course; these use this chapter's idea too. The note says what to look for.
- #14Longest Common PrefixEasyin Arrays & Strings
The common prefix is the trie's single lane from the root — try its trie approach, then compare it with the simpler column scan.
11 · revise
The whole chapter on one screen
9 cards, about a minute. Read them the night before an interview, or right after the chapter to lock it in.
- what it is
A tree of characters: each edge is a letter, each node a prefix, and an
isEndflag marks where a stored word ends. Shared beginnings are stored once. - use it when
Prefix questions over one set of strings: startsWith, autocomplete, shortest root, many words on one board, wildcard search — and max XOR with a binary trie.
- template
for (char ch : w.toCharArray()) { int i = ch - 'a'; if (cur.children[i] == null) cur.children[i] = new Node(); cur = cur.children[i]; }thencur.isEnd = true; - cost
insert / search / startsWith = O(L) for an L-letter word, whatever the number of words. Memory: up to one node per stored letter, 26 slots each with
Node[26]. - trap
searchmust checkisEndat the last node — otherwise "app" is "found" after inserting only "apple". - trap
ch - 'a'assumes lowercase a–z. Uppercase, digits or spaces give an index outside 0..25 → ArrayIndexOutOfBoundsException. Use a HashMap per node. - pro tip
Many words, one board? Build one trie, run one DFS that follows it, prune when no word continues. Store the whole word on its end node.
- pro tip
Max XOR: insert bits 30 → 0 into a binary trie; at each bit take the opposite child if it exists. A higher bit beats all lower bits together.
- pro tip
Top-k suggestions fast: insert words in sorted order and keep the first k on every node — each typed letter is then O(1).
12 · recall
Flip, remember, repeat
What does one trie node hold, and what does a node stand for?
Question 1: What does one trie node hold, and what does a node stand for?
13 · check yourself
Quick quiz
You insert only "apple". What do search("app") and startsWith("app") return?
A trie stores 1 million words. How many steps does search("hello") take?
When is `HashMap<Character, Node>` children a better choice than `Node[26]`?
WordDictionary holds "bad", "bat" and "map". Where does search("b.d") branch?
In Word Search II, what does the trie let the DFS do that running Word Search I per word cannot?
Maximum XOR with a binary trie: why must you walk bits from the highest to the lowest?
In a counting trie, "bat" and "bath" are stored. You erase "bath". What happens?
Autocomplete returns results in alphabetical order without sorting. Why?
14 · learn more
A second teacher, if you want one
- ▶ playlistTrie Series | Striver ↗Striver (take U forward) · EnglishSeven focused lessons: implement a trie, then use it for prefix counts, distinct substrings and maximum XOR.
- ◈ visualizerTrie Visualization ↗David Galles, University of San Francisco · EnglishInsert and find words, and watch shared prefixes get reused. It's a quick way to see why a trie saves work.
- ▶ videoTrie Data Structure | Java DSA Course ↗Apna College · HindiThe trie node class, insert and search built step by step in Java, with notes linked.