Word Search in Grid Using Backtracking in DSA Python - Time & Space Complexity
We want to understand how the time needed to find a word in a grid changes as the grid or word size grows.
How does the search effort increase when the grid or word gets bigger?
Analyze the time complexity of the following code snippet.
def exist(board, word):
rows, cols = len(board), len(board[0])
def backtrack(r, c, index):
if index == len(word):
return True
if r < 0 or c < 0 or r >= rows or c >= cols or board[r][c] != word[index]:
return False
temp = board[r][c]
board[r][c] = '#'
found = (backtrack(r+1, c, index+1) or
backtrack(r-1, c, index+1) or
backtrack(r, c+1, index+1) or
backtrack(r, c-1, index+1))
board[r][c] = temp
return found
for i in range(rows):
for j in range(cols):
if backtrack(i, j, 0):
return True
return False
This code tries to find if a word exists in the grid by exploring all possible paths using backtracking.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The backtracking function explores up to 4 directions recursively for each letter in the word.
- How many times: For each cell in the grid (rows * cols), backtracking can explore up to 4 recursive calls per letter in the word.
As the grid size or word length grows, the number of paths to explore grows very fast because each letter can lead to 4 new directions.
| Input Size (n = word length) | Approx. Operations |
|---|---|
| 3 | Up to 4^3 = 64 recursive calls per starting cell |
| 5 | Up to 4^5 = 1024 recursive calls per starting cell |
| 10 | Up to 4^10 = 1,048,576 recursive calls per starting cell |
Pattern observation: The number of operations grows exponentially with the word length, making the search much slower for longer words.
Time Complexity: O(M * N * 4^L)
This means the time grows very fast with the word length L, and also depends on the grid size M rows and N columns.
[X] Wrong: "The search only checks each cell once, so it is O(M*N)."
[OK] Correct: Because the search explores many paths recursively for each letter, it can revisit cells in different paths, causing exponential growth, not just a simple grid scan.
Understanding this complexity helps you explain why backtracking can be slow and when it is suitable, showing your grasp of algorithm efficiency in real problems.
"What if we limited the search to only move right and down instead of all four directions? How would the time complexity change?"
Practice
Solution
Step 1: Understand backtracking in word search
Backtracking tries all possible paths in the grid to find the target word by exploring neighbors recursively.Step 2: Eliminate unrelated options
Sorting, counting words, or replacing characters are not related to backtracking's purpose in this problem.Final Answer:
To explore all possible paths to find the word -> Option DQuick Check:
Backtracking = Explore paths [OK]
- Thinking backtracking sorts or modifies the grid
- Confusing backtracking with simple searching
- Ignoring the recursive exploration nature
Solution
Step 1: Understand grid boundary conditions
Valid indices must be greater or equal to 0 and less than the number of rows or columns.Step 2: Analyze each option
if 0 <= row < len(grid) and 0 <= col < len(grid[0]): correctly uses inclusive lower bound and exclusive upper bound checks. if row > 0 and col > 0 and row < len(grid) and col < len(grid[0]): excludes 0 index, which is invalid. if row <= len(grid) and col <= len(grid[0]): allows equal to length, which is out of range. if row >= 0 or col >= 0: uses 'or' which is incorrect logic.Final Answer:
if 0 <= row < len(grid) and 0 <= col < len(grid[0]): -> Option AQuick Check:
Boundary check = if 0 <= row < len(grid) and 0 <= col < len(grid[0]): [OK]
- Using > 0 instead of >= 0 excludes first row/column
- Allowing index equal to length causes errors
- Using 'or' instead of 'and' in conditions
grid = [['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']]
word = "ABCCED"
# Function to check word existence
result = word_search(grid, word)
print(result)
# Assume word_search uses backtracking to find the wordSolution
Step 1: Understand the word and grid
The word "ABCCED" can be found by moving right and down in the grid starting at grid[0][0].Step 2: Confirm backtracking finds the word
Backtracking explores neighbors and matches letters sequentially, so it returns True if the word exists.Final Answer:
True -> Option AQuick Check:
Word found = True [OK]
- Assuming word is not found without tracing
- Confusing output with None or error
- Ignoring backtracking's path exploration
def backtrack(r, c, index):
if index == len(word):
return True
if r < 0 or c < 0 or r >= len(grid) or c >= len(grid[0]) or grid[r][c] != word[index]:
return False
temp = grid[r][c]
grid[r][c] = '#'
found = (backtrack(r+1, c, index+1) or
backtrack(r-1, c, index+1) or
backtrack(r, c+1, index+1) or
backtrack(r, c-1, index+1))
grid[r][c] = temp
return foundSolution
Step 1: Analyze the backtracking logic
The code marks visited cells with '#', explores neighbors recursively, and restores the cell after exploration.Step 2: Check for bugs
Restoring the cell after recursion prevents errors. Base case for index == len(word) is correct. '#' is a common marker and safe if not in original grid.Final Answer:
No bug; code is correct -> Option CQuick Check:
Code logic = Correct [OK]
- Forgetting to restore grid cell after recursion
- Adding unnecessary base cases
- Assuming marker conflicts without checking grid content
Solution
Step 1: Understand the problem of multiple words
Running backtracking separately for each word is inefficient because it repeats searches.Step 2: Use Trie to optimize search
Building a Trie of all words allows a single backtracking pass to find all words by prefix matching, improving efficiency.Step 3: Eliminate other options
Searching only first letters or sorting words does not improve search efficiency significantly.Final Answer:
Build a Trie of words and backtrack once to find all words simultaneously. -> Option BQuick Check:
Trie + backtracking = Efficient multi-word search [OK]
- Running backtracking repeatedly wastes time
- Ignoring prefix sharing among words
- Assuming sorting helps search efficiency
Ready to prove it?
Pass the test and this pattern moves unknown
