Word Search Ii - JS Solution

JS
Editorial

Solution explanation

Solution explanation

Approach

We combine a Trie (prefix tree) with DFS backtracking on the board to efficiently find all words. Instead of storing full words at Trie nodes, we store their indices in the original words array. This avoids redundant string storage while still enabling fast lookup, and simplifying duplicate handling by clearing the stored index at a node once its corresponding word is found.

🧱 Trie Construction

  • Each TrieNode contains:
    • children: maps each character to the next TrieNode, forming the links that build word paths through the Trie.
    • wordIndex: initially null; set to the index of a word in the words array when a complete word ends at this node.
  • For each word words[i]:
    • Walk from the root, creating child nodes as needed for each character.
    • At the final node, set node.wordIndex = i, meaning: β€œthe path from root to this node exactly spells words[i]”.

πŸ” DFS on the Board + Trie

  • We iterate over every cell [row, col] of the board and start a DFS from there.
  • At each DFS step:
    • Use the current board character to move along the Trie via children[char]. If no matching child exists, this path cannot form any word β†’ prune immediately.
    • If the resulting Trie node has wordIndex !== null, we have matched a full word:
      • Retrieve it as words[wordIndex] and add it to the result list.
      • Set wordIndex = null on that node to avoid counting the same word again from other paths (this handles duplicates cleanly).
    • Mark the current board cell as visited by setting it to '#' so it cannot be reused in the same path.
    • Recurse into up to 4 neighbors (up, down, left, right) that are inside bounds and not '#'.
    • After exploring all neighbors, restore the original character in the cell to make it available again for future DFS explorations.

🧠 Why Index Storage?

  • Avoid copying full strings into Trie nodes.
  • Directly map a terminal node back to words[wordIndex] when a match is found.
  • Can β€œconsume” a found word by setting wordIndex = null, preventing duplicates in a simple, constant-time way.

Time Complexity

Let N be the total number of cells in the board, K be the total number of characters across all inserted words, and L be the maximum word length.

  • Building the Trie: O(K) β€” each character from every word is processed once, resulting in a total cost proportional to the sum of all word lengths.
  • DFS traversal: O(N Γ— 3L) in the worst case β€” we start a DFS from every cell (N), and each search can branch to up to 4 directions initially, but to at most 3 directions afterward since we never revisit the previous cell.

Overall time complexity: O(K + N Γ— 3L), where O(K) comes from Trie construction and O(N Γ— 3L) from DFS explorations.

Space Complexity

Let K be the total number of characters across all inserted words, and L be the maximum word length.

  • Trie storage: O(K) β€” each unique prefix is stored once across all words. In the worst case (when no prefixes are shared), every character requires a new node, resulting in O(K) nodes in total.
  • DFS recursion stack: O(L) β€” the maximum call depth equals the length of the longest word since each recursive call represents one character in the current search path.

Overall space complexity: O(K), since L cannot exceed K.

Visucodize editorial solution titled JS Solution for LeetCode's Word Search Ii 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-ii.