TREES, TRIES & HEAPS / ALGORITHM BRIEF

Trie

A trie (prefix tree) stores strings character by character along paths from the root.

IntermediatePhase 04 / Topic 6 of 8Mental modelComplexityEdge cases
01

Overview

A trie (prefix tree) stores strings character by character along paths from the root. Each node represents a prefix, has children for the next possible characters, and a flag marking whether a complete word ends there. Words that share a prefix share the same path.

Insert and search take O(L), where L is the word length, independent of how many words are stored. The real strength is prefix queries: finding all words that start with 'app' means walking three nodes and then collecting that subtree, which a hash set cannot do efficiently.

A phone contact search

As you type 'D', 'a', 'r', the list narrows to names starting with those letters. Each typed letter moves one step down a shared path; you never scan every contact.

02

When to use it

  • Autocomplete and 'starts with' queries.
  • Many words must be searched in a grid or text at once (word search II).
  • Longest common prefix, or the shortest unique prefix of words.
  • Wildcard search where '.' matches any character.
  • Maximum XOR of two numbers (a binary trie over bits).
03

Problem patterns it solves

Prefix search

Recognize it when: starts with, autocomplete, suggestions.

  • 208. Implement Trie (Prefix Tree)
  • 1268. Search Suggestions System
  • 14. Longest Common Prefix
Wildcard matching

Recognize it when: '.' matches any letter; DFS through all children at wildcards.

  • 211. Design Add and Search Words Data Structure
Many words in a grid

Recognize it when: find every dictionary word on a board; prune DFS by prefix.

  • 212. Word Search II
Replace / shortest root

Recognize it when: replace words by their shortest dictionary prefix.

  • 648. Replace Words
  • 720. Longest Word in Dictionary
Binary trie for XOR

Recognize it when: maximize XOR by choosing opposite bits greedily.

  • 421. Maximum XOR of Two Numbers in an Array
  • 1707. Maximum XOR With an Element From Array
04

Where it is used in real software

Search box autocomplete

Search engines and IDEs suggest completions by walking a prefix tree (often compressed and ranked by popularity).

IP routing tables

Routers find the longest matching network prefix for a destination IP with binary tries (Patricia or radix trees).

Spell checkers

Dictionaries stored as tries allow fast lookups and nearby-word suggestions.

Web frameworks

HTTP routers in Go (httprouter) and Node.js (find-my-way used by Fastify) match URL paths with radix trees.

05

Key terms

Node
Holds children (map or array of 26) and an isEnd flag.
Prefix
The path from the root to a node.
isEnd
True when a stored word ends at this node.
Radix / compressed trie
Merges single-child chains into one edge labeled with a string.
06

How it works, step by step

  1. 1
    Insert

    For each character, create the child if missing and move to it. Mark isEnd at the last node.

  2. 2
    Search a word

    Follow characters; if any child is missing return false; at the end return node.isEnd.

  3. 3
    startsWith

    Same walk, but return true if the path exists, regardless of isEnd.

  4. 4
    Collect words under a prefix

    Walk to the prefix node, then DFS its subtree, building strings.

07

Insert "app", "apple", "apt", then query

Root -> a -> p -> p (end) -> l -> e (end); p -> t (end)

Step 1 / 5
QueryPath walkedResultWhy
search("app")a, p, ptrueisEnd is set at the second p
search("ap")a, pfalsepath exists but no word ends there
startsWith("ap")a, ptruepath exists
search("apple")a, p, p, l, etrueisEnd at e
search("apx")a, p, x missingfalseno child x

NOWQuery: search("app") | Path walked: a, p, p | Result: true | Why: isEnd is set at the second p

All three words share the nodes a and p. Every query costs only the length of the query string.

08

Implementation

class TrieNode {  constructor() {    this.children = new Map();    this.isEnd = false;  }} class Trie {  constructor() { this.root = new TrieNode(); }   insert(word) {    let node = this.root;    for (const ch of word) {      if (!node.children.has(ch)) node.children.set(ch, new TrieNode());      node = node.children.get(ch);    }    node.isEnd = true;  }   #walk(prefix) {    let node = this.root;    for (const ch of prefix) {      node = node.children.get(ch);      if (!node) return null;    }    return node;  }   search(word) { return this.#walk(word)?.isEnd === true; }  startsWith(prefix) { return this.#walk(prefix) !== null; }   suggestions(prefix, limit = 3) {    const start = this.#walk(prefix);    const result = [];    const dfs = (node, path) => {      if (result.length === limit) return;      if (node.isEnd) result.push(path);      for (const ch of [...node.children.keys()].sort()) dfs(node.children.get(ch), path + ch);    };    if (start) dfs(start, prefix);    return result;  }} // 211: '.' matches any characterfunction searchWithDots(node, word, i = 0) {  if (i === word.length) return node.isEnd;  if (word[i] === ".") {    for (const child of node.children.values()) if (searchWithDots(child, word, i + 1)) return true;    return false;  }  const child = node.children.get(word[i]);  return child ? searchWithDots(child, word, i + 1) : false;}
09

Complexity and performance

Insert / search / startsWithO(L)

L = length of the word or prefix.

SpaceO(total characters)

Worst case N words x L characters nodes.

Array children26 pointers per node

Fast but memory-heavy; Map is compact.

10

Trade-offs

Trie vs hash set

A hash set checks whole words in O(L) too, but cannot answer prefix queries without scanning all words.

Array vs map children

Arrays of 26 are fastest for lowercase English; maps save memory for large or sparse alphabets.

Memory

Tries can use much more memory than the strings themselves; radix trees compress chains to reduce it.

11

Variants and related techniques

Radix tree / Patricia trie

Edges hold substrings; used in routers and HTTP routing.

Binary trie

Each node has children 0 and 1 for bits; answers maximum XOR queries in O(32).

Suffix trie / tree

Stores all suffixes of a string for fast substring search.

Counts at nodes

Store how many words pass through each node to count words with a prefix.

12

Common mistakes

  • Returning true for search on a prefix that is not a word.

    Fix: Check isEnd at the final node.

  • Duplicate results in Word Search II.

    Fix: Clear the stored word after finding it.

  • Not pruning.

    Fix: Stop DFS as soon as the current prefix has no trie node.

13

Interview questions

Why use a trie over a hash set for autocomplete?

A trie walks to the prefix in O(L) and only explores matching words. A hash set would have to check every stored word for the prefix.

How does a trie speed up Word Search II?

Instead of running a separate search for each word, one DFS over the board follows trie nodes, and stops immediately when the current path is not a prefix of any word.

14

Practice problems

ProblemDifficultyWhat it trains
208. Implement Trie (Prefix Tree)MediumCore operations.
211. Design Add and Search Words Data StructureMediumWildcard DFS.
648. Replace WordsMediumShortest root prefix.
1268. Search Suggestions SystemMediumSorted suggestions.
421. Maximum XOR of Two Numbers in an ArrayMediumBinary trie.
212. Word Search IIHardTrie-guided backtracking.