Word Search II
Find all dictionary words on a board — Trie of words + DFS from each cell, prune dead branches.
advanced3 min read
- dsa
- trie
- interview
- Meta
- Amazon
- Microsoft
The problem
m × n board of letters and a list of words. Return all words that can be formed by adjacent (4-dir) letters without reusing a cell in one word. Same as Word Search but many words.
board = [["o","a","a","n"],
["e","t","a","e"],
["i","h","k","r"],
["i","f","l","v"]]
words = ["oath","pea","eat","rain"]
Output: ["eat","oath"]
Brute force
Run Word Search I for each word independently. O(words · m · n · 4^L) — too slow when word list is large.
Optimal: Trie + board DFS
- Insert all words into a trie.
- DFS from every cell; walk trie in parallel.
- When a node marks word end, record it (and optionally clear to avoid dupes).
- Prune empty trie branches.
class TrieNode {
children = new Map<string, TrieNode>();
word: string | null = null;
}
function findWords(board: string[][], words: string[]): string[] {
const root = new TrieNode();
for (const w of words) {
let node = root;
for (const ch of w) {
if (!node.children.has(ch)) node.children.set(ch, new TrieNode());
node = node.children.get(ch)!;
}
node.word = w;
}
const rows = board.length;
const cols = board[0].length;
const res: string[] = [];
const dirs = [[1,0],[-1,0],[0,1],[0,-1]];
function dfs(r: number, c: number, node: TrieNode): void {
const ch = board[r][c];
const next = node.children.get(ch);
if (!next) return;
if (next.word) {
res.push(next.word);
next.word = null; // dedupe
}
board[r][c] = "#";
for (const [dr, dc] of dirs) {
const nr = r + dr, nc = c + dc;
if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;
if (board[nr][nc] === "#") continue;
dfs(nr, nc, next);
}
board[r][c] = ch;
// optional prune
if (next.children.size === 0) node.children.delete(ch);
}
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
dfs(r, c, root);
}
}
return res;
}
| Time | O(m · n · 4 · 3^{L-1}) worst board search shared across trie |
| Space | O(total characters in words) |
Edge cases
- Empty words / empty board
- Duplicate words in list
- Word longer than board cells
- Overlapping paths for different words
Common bugs
- Not restoring board cell after DFS
- Forgetting to dedupe found words
- Building trie wrong (shared prefixes mishandled)
- 8-directional neighbors
Interview delivery
- Many words → trie, not N× search.
- DFS board + trie node.
- Mark visited with mutation.
- Prune / dedupe.
- Contrast with Word Search I.