Word Search - JS Solution

JS
Editorial

Solution explanation

Solution explanation

Approach

We determine whether the word exists by performing a depth-first search (DFS) with backtracking from every cell in the board. From each starting position, we attempt to match the target word character by character, moving one step at a time in the four cardinal directions (down, up, right, left) without revisiting any cell in the same path.

  • Start from every cell:
    Iterate over all (rowIndex, colIndex) positions. For each cell, start a DFS backtracking search to form the entire word beginning at that cell (with wordIndex = 0). If any DFS call matches all characters, return true immediately.
  • Recursive function (backtrack): The function backtrack(board, word, rowIndex, colIndex, wordIndex) attempts to match the remaining part of the word starting from wordIndex, beginning the search from the cell at (rowIndex, colIndex) on the board.
    • โœ… Base case: If wordIndex === word.length, the entire word is matched โ€” return true.
    • ๐Ÿšซ Boundary / mismatch check: If the cell is out of bounds or board[rowIndex][colIndex] !== word[wordIndex] (which also covers cases where the cell was already marked as visited with "#"), this path fails โ€” return false.
  • Mark โ†’ Explore โ†’ Restore:
    • Mark as visited: Temporarily set board[rowIndex][colIndex] = "#" to prevent revisiting the same cell in the current exploration path, avoiding cycles.
    • Explore four directions: Recurse to each neighboring cell โ€” down, up, right, and left โ€” passing wordIndex + 1 as the new wordIndex parameter. This advances the search to the next character of the word after a successful match, continuing the path in all possible directions.
    • Backtrack (restore): If none of the recursive calls succeed, restore the original character before returning false, allowing the cell to be used again in other paths.
  • Why this works:
    • Each recursive call explores all valid continuations of the current prefix.
    • Marking visited cells prevents infinite loops or reuse of a cell in one path.
    • Restoring the character ensures correctness for later explorations.
    • By starting from every cell, we cover all possible placements of the word on the board.
  • Result: If any DFS path returns true, the word exists in the board. Otherwise, after all starting positions are tested without finding a complete match, the result is false.

Time Complexity

Let m and n be the board dimensions and L be the word length. The worst-case running time is O(m ยท n ยท 3L).

  • Starting points: We may start a DFS from any of the m ยท n cells.
  • Branching factor: At the first character there are at most 4 choices (up/down/left/right). After moving once, you cannot immediately return to the previous cell, leaving at most 3 choices per subsequent step.
  • Depth: The search depth is the word length L, yielding โ‰ˆ 4 ร— 3Lโˆ’1 paths per start. This is asymptotically O(3L) per start.

Combining both factors gives O(m ยท n ยท 3L).

Space Complexity

The algorithm uses O(L) auxiliary space, where L is the length of the target word.

  • Recursion stack: Each recursive DFS call corresponds to one character of the word, leading to a maximum recursion depth of L.
  • In-place marking: The board itself is modified temporarily (by setting visited cells to "#"), so no extra visited matrix is required.

Hence, the overall auxiliary space complexity is O(L).

Visucodize editorial solution titled JS Solution for LeetCode's Word Search coding problem. Includes code and may include explanation. You can animate the code step by step using the provided input by clicking the run button, or fork it locally to update the code and input for custom visualization. View the original problem at https://leetcode.com/problems/word-search.