You're given an m x n grid of letters called board and a target string word. Return true if word can be spelled out by walking through the grid, and false otherwise.
A path may start at any cell. From a cell you may step to a horizontally or vertically adjacent cell — up, down, left, or right, never diagonally. Each step must land on the next letter of word, and no cell may be used more than once within a single path.
word — any leftover cells are ignored.word needs more of some letter than the board holds, return early; and search from the rarer endpoint by reversing word when its last letter is scarcer than its first.Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" Output: true Trace A(0,0) → B(0,1) → C(0,2) → C(1,2) → E(2,2) → D(2,1).
Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE" Output: true Trace S(1,3) → E(2,3) → E(2,2).
Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB" Output: false The only path spelling ABC dead-ends; the second B is never reachable without reusing a cell.
- m == board.length - n == board[i].length - 1 <= m, n <= 6 - 1 <= word.length <= 15 - board and word consist of only lowercase and uppercase English letters.
Word Search is the canonical first step into backtracking on a grid — searching for a path, undoing your choices, and pruning dead ends. Here's the arc from a plain scan to a pruned search.
Formally: starting from some cell, can you form word by moving through orthogonally adjacent cells, matching letter by letter, using each cell at most once along the path?
Worked example — word = SEE
A B C E S F C S A D E E start (1,3)=S → (2,3)=E → (2,2)=E spells S-E-E ✓ answer: true
Asking these before coding shows you're mapping the rules of movement, not guessing.
“Are diagonal steps allowed, or only up-down-left-right?”
Diagonals would add four more directions to every recursive call.
“Can the same cell be used twice in one word?”
No reuse per path is the whole reason we mark and restore cells.
“How large can the board and word get?”
Tiny here (m, n <= 6), so plain backtracking passes; larger boards would need pruning.
Before I code, a couple of clarifications.
Are moves strictly horizontal and vertical, with no diagonals?
And within a single path, a cell can't be reused — correct?
Every valid path's first cell equals word[0], so we only launch a search from those cells — a mismatch elsewhere dies instantly.
Before recursing into a cell's neighbors, overwrite it with a sentinel like #; restore it afterward. No separate visited-set to keep in sync.
visit (0,0)=A → board[0][0]='#'
... explore neighbors ...
done → board[0][0]='A' (restored)The first letter mismatch kills a branch. For larger boards, if the last letter is rarer than the first, search the word reversed so fewer branches ever start.
| Brute force | Optimal | |
|---|---|---|
| Time | O(m·n·4^L) | O(m·n·4^L) worst, pruned in practice |
| Space | O(L) | O(L) |
| Extra work | searches every start | skips impossible words, starts from rarer end |
See the full code for each approach in the Approaches selector below.
Key takeaway
Word Search is grid backtracking: choose a cell, mark it, explore its neighbors, then un-mark it. Add a feasibility check and a rare-end start when the board grows.
for each cell (r,c):
if dfs(r, c, 0): return true
return false
dfs(r, c, i):
if out of bounds or board[r][c] != word[i]: return false
if i == last index: return true
save board[r][c]; board[r][c] = '#'
found = dfs(up) or dfs(down) or dfs(left) or dfs(right)
restore board[r][c]
return found