Skip to content
AI360Xpert
Beta
Difficulty: HardTries

Word Search II

Problem in Plain English

Given a board of letters and a long list of candidate words, return every word that can be spelled by stepping through horizontally or vertically adjacent cells. No cell may be reused within a single word.

Problem Statement

Given an m x n board of characters and a list of strings words, return all words that appear on the board.

Each word must be built from sequentially adjacent cells, where adjacent means sharing a side horizontally or vertically. The same cell may not be used twice within one word, and each listed word is reported at most once.

Constraints

  • m == board.length
  • n == board[i].length
  • Board dimensions satisfy 1≤m,n≤121 \leq m,n \leq 12.
  • board[i][j] is a lowercase English letter.
  • The candidate count is between 1 and 3×1043 \times 10^4.
  • Every word length is between 1 and 10.
  • words[i] consists of lowercase English letters.
  • All strings in words are unique.

Examples

Example 1

Input
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"]

The board spells oath down the path (0,0) to (0,1) to (1,1) to (2,1), and spells eat nearby, while pea and rain cannot be completed.

Example 2

Input
board = [["a","b"],["c","d"]], words = ["abcb"]
Output
[]

No path spells abcb. From the top-left a, the only b is top-right; its unused neighbor is d, not c. The bottom-left c is diagonal to b, which is forbidden. Reusing any earlier cell is also forbidden.

Example 3

Input
board = [["a","a"]], words = ["a","aa","aaa"]
Output
["a","aa"]

Either cell spells a, but that word is returned only once. Both cells together spell aa. aaa would reuse a cell, so it fails. Finding the shorter word must not stop the search for the longer one sharing its prefix; output order is arbitrary.

Intuition

A grid path must follow matching letters without revisiting a cell. Searching separately for oath, pea, eat and rain repeats this work, while a trie stores all candidate prefixes so one path can test several words together. In Example 1, o → a → t → h reaches the terminal for oath; an unrecognized prefix can stop immediately. A temporary visited marker belongs only to the current path and must be restored before another path begins.

Approaches

DFS per Word

Solution Details

Reveal DFS per Word: intuition, complexity, and code

Hints

Hint 1
Searching the board once per word repeats the same walks thousands of times, so look for a way to test all words together.
Hint 2
A trie of the candidates tells you instantly whether the current path is still a prefix of anything worth finishing.
Hint 3
When a word is found, erase it from its terminal node so later paths cannot report it a second time.

Edge Cases

  • A word longer than the total cell count, which is impossible without reusing cells.
  • Candidates sharing long prefixes, such as app and apple, which the trie explores together.
  • A word reachable by several routes, which must still appear only once in the answer.
  • A one-cell board can match only a one-letter word, and many routes spelling the same word still produce one result.
  • Calling the same solver again must build a fresh trie and fresh result; previously returned lists remain unchanged.

Common Mistakes and Interview Tips

  • Forgetting to restore the cell letter after exploring its neighbors, which blocks every later path through that cell.
  • Reporting a found word every time its path is walked instead of clearing it from the trie node.
  • Carrying the built-up string through the search and testing prefixes by scanning, which loses the whole point of the trie.
  • Returning immediately on a trie terminal and missing longer words that share its prefix.
  • Clearing or reordering the input dictionary to deduplicate results; clear only the private trie terminal payload.
  • Keeping a Java result list as an accumulating field across calls; replace it with a fresh list for each invocation.

Key Takeaway

When one grid must be tested against a whole dictionary, plant the dictionary in a trie and let one backtracking walk prune every dead prefix at once.