Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Word Search II in Python
The Word Search II problem involves finding all words from a dictionary that can be formed in a 2D character board. Each word must be constructed from letters of sequentially adjacent cells (horizontally or vertically neighboring), and the same letter cell cannot be used more than once in a single word.
This problem is efficiently solved using a Trie (prefix tree) data structure combined with backtracking. The Trie allows us to prune search paths early when no dictionary word has the current prefix.
Algorithm Overview
The solution follows these key steps ?
Build a Trie from all dictionary words
For each cell in the board, start a DFS search
Use backtracking to explore all possible paths
Mark visited cells temporarily to avoid reuse
When a complete word is found, add it to results
Example
Let's implement the complete solution ?
class Solution:
def findWords(self, board, words):
self.result = []
trie = {}
# Build Trie from dictionary words
for word in words:
self.insert_word(word, trie)
# Search for words starting from each cell
for i in range(len(board)):
for j in range(len(board[0])):
self.search(board, trie, i, j, "")
return self.result
def insert_word(self, word, trie):
"""Insert a word into the Trie"""
current = trie
for char in word:
if char not in current:
current[char] = {}
current = current[char]
current['#'] = True # Mark end of word
def search(self, board, trie_node, i, j, current_word=""):
"""DFS search with backtracking"""
# Check bounds
if i < 0 or j < 0 or i >= len(board) or j >= len(board[0]):
return
char = board[i][j]
# Check if current character exists in Trie
if char not in trie_node:
return
# Move to next Trie node and build word
trie_node = trie_node[char]
current_word += char
# Check if we found a complete word
if '#' in trie_node and trie_node['#']:
self.result.append(current_word)
trie_node['#'] = False # Avoid duplicates
# Mark cell as visited
board[i][j] = '*'
# Explore all 4 directions
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
for di, dj in directions:
self.search(board, trie_node, i + di, j + dj, current_word)
# Restore cell (backtrack)
board[i][j] = char
# Test the solution
solution = Solution()
board = [
["o", "a", "a", "n"],
["e", "t", "e", "a"],
["i", "h", "k", "r"],
["i", "f", "l", "v"]
]
words = ["oath", "pea", "tea", "rain"]
result = solution.findWords(board, words)
print("Found words:", result)
Found words: ['oath', 'tea']
How It Works
The algorithm uses a Trie data structure to store all dictionary words efficiently. During the search phase ?
Trie Construction: Each word is inserted character by character, with '#' marking word endings
Board Traversal: Starting from each cell, we perform DFS
Path Validation: We only continue if the current path exists in the Trie
Backtracking: We mark cells as visited ('*') during search, then restore them
Word Detection: When we reach a '#' marker, we've found a complete word
Time and Space Complexity
The solution has the following complexity ?
Time Complexity: O(M × N × 4^L) where M×N is board size and L is maximum word length
Space Complexity: O(K × L) for the Trie, where K is number of words
Key Optimizations
Early Pruning: Trie structure eliminates impossible paths early
Duplicate Prevention: Setting trie_node['#'] = False prevents duplicate results
Backtracking: Allows reusing cells for different words
Conclusion
Word Search II efficiently finds all dictionary words in a 2D board using Trie for prefix matching and backtracking for path exploration. The Trie structure provides significant optimization by pruning impossible search paths early.
