PracticeNeetCode ↗LeetCode ↗
Given an m×n grid of characters board and a string word, return true if word can be formed by a path of sequentially adjacent cells (horizontally or vertically), where no single cell is reused within one word.
"#") instead of a separate visited set — cheaper, and trivially undone on backtrack.(r, c), call dfs(r, c, 0) — 0 is the index into word being matched.dfs: if the index equals len(word), the whole word matched — return True.(r, c) is out of bounds, or board[r][c] != word[index], return False.board[r][c] visited, recurse into all 4 neighbors with index + 1, restore board[r][c] afterward, and return True if any neighbor succeeded.True as soon as any starting cell's dfs succeeds; otherwise False once every cell is exhausted.Time: O(m · n · 4^L) where L = len(word) — Space: O(L) recursion depth
def exist(board: list[list[str]], word: str) -> bool:
rows, cols = len(board), len(board[0])
def dfs(r: int, c: int, i: int) -> bool:
if i == len(word):
return True
if r < 0 or c < 0 or r >= rows or c >= cols or board[r][c] != word[i]:
return False
temp = board[r][c]
board[r][c] = "#"
found = (
dfs(r + 1, c, i + 1)
or dfs(r - 1, c, i + 1)
or dfs(r, c + 1, i + 1)
or dfs(r, c - 1, i + 1)
)
board[r][c] = temp
return found
for r in range(rows):
for c in range(cols):
if dfs(r, c, 0):
return True
return FalseHow the solution above works, piece by piece.
dfs(r, c, i) checks whether word[i:] can be spelled starting at (r, c). If i == len(word), every letter matched.word[i].# (visited), try all 4 neighbours for the next letter, then restore the letter. The or chain stops at the first success.Running it on the example board with word = "ABCCED":
# into a visited cell stops the path from using the same cell twice.