THN Interview Prep

79. Word Search

At a Glance

  • Topic: backtracking
  • Pattern: DFS / Backtracking
  • Difficulty: Medium
  • Companies: Amazon, Meta, Microsoft, Google, Apple
  • Frequency: Very High
  • LeetCode: 79

Problem (one-liner)

In a 2D grid of letters, determine if word exists as a path moving up/down/left/right using each cell at most once per path.

Recognition Cues

  • Path in grid with visit once constraint
  • Backtrack after failed branch — mark visited, recurse, unmark
  • Word length × board size bounds search

Diagram

At-a-glance flow (replace with problem-specific Mermaid as you refine this note). camelCase node IDs; no spaces in IDs.

Loading diagram…

Approaches

  • BFS per start — harder for full word (path state explosion).
  • Optimal — DFS from each cell matching prefix — O(n * m * 4^L) worst.

Optimal Solution

Go

func exist(board [][]byte, word string) bool {
	rows := len(board)
	cols := len(board[0])

	var dfs func(row int, col int, position int) bool
	dfs = func(row int, col int, position int) bool {
		if position == len(word) {
			return true
		}
		if row < 0 || col < 0 || row >= rows || col >= cols {
			return false
		}
		if board[row][col] != word[position] {
			return false
		}
		temp := board[row][col]
		board[row][col] = '#'
		found := dfs(row+1, col, position+1) ||
			dfs(row-1, col, position+1) ||
			dfs(row, col+1, position+1) ||
			dfs(row, col-1, position+1)
		board[row][col] = temp
		return found
	}

	for row := 0; row < rows; row++ {
		for col := 0; col < cols; col++ {
			if dfs(row, col, 0) {
				return true
			}
		}
	}
	return false
}

JavaScript

function exist(board, word) {
  const rows = board.length;
  const cols = board[0].length;

  function dfs(row, col, position) {
    if (position === word.length) {
      return true;
    }
    if (row < 0 || col < 0 || row >= rows || col >= cols) {
      return false;
    }
    if (board[row][col] !== word[position]) {
      return false;
    }
    const temp = board[row][col];
    board[row][col] = '#';
    const found =
      dfs(row + 1, col, position + 1) ||
      dfs(row - 1, col, position + 1) ||
      dfs(row, col + 1, position + 1) ||
      dfs(row, col - 1, position + 1);
    board[row][col] = temp;
    return found;
  }

  for (let row = 0; row < rows; row += 1) {
    for (let col = 0; col < cols; col += 1) {
      if (dfs(row, col, 0)) {
        return true;
      }
    }
  }
  return false;
}

Walkthrough

Board A B C, search AB. From (0,0) match A, DFS neighbors find B.

Invariant: Modified # marks current path; restored before returning so sibling branches see original letters.

Edge Cases

  • Word longer than cells count — impossible
  • Single-letter word
  • Repeated letters — still one visit per path

Pitfalls

  • Reusing a visited cell in same path — must mark
  • Not restoring board — breaks other DFS roots

Similar Problems

Variants

  • Word Search II — trie + DFS from each cell (batch queries)

Mind-Map Tags

#dfs #grid #backtracking #path #string

Last updated on

Spotted something unclear or wrong on this page?

On this page