Word Search in Grid Using Backtracking in DSA Java - Time & Space Complexity
We want to understand how the time needed to find a word in a grid grows as the grid or word size increases.
How does the search effort change when the grid or word gets bigger?
Analyze the time complexity of the following code snippet.
public boolean exist(char[][] board, String word) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (backtrack(board, word, i, j, 0)) return true;
}
}
return false;
}
private boolean backtrack(char[][] board, String word, int i, int j, int index) {
if (index == word.length()) return true;
if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || board[i][j] != word.charAt(index)) return false;
char temp = board[i][j];
board[i][j] = '#';
boolean found = backtrack(board, word, i + 1, j, index + 1) ||
backtrack(board, word, i - 1, j, index + 1) ||
backtrack(board, word, i, j + 1, index + 1) ||
backtrack(board, word, i, j - 1, index + 1);
board[i][j] = temp;
return found;
}
This code tries to find a word in a 2D grid by checking each cell and exploring neighbors recursively.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive backtracking exploring up to 4 directions per character.
- How many times: For each cell in the grid (m x n), it may explore up to 4 recursive calls per character in the word (length k).
As the grid size or word length grows, the search tries many paths, growing very fast.
| Input Size (m x n, k) | Approx. Operations |
|---|---|
| 3 x 3 grid, word length 3 | Up to 9 * 4^3 = 576 |
| 5 x 5 grid, word length 5 | Up to 25 * 4^5 = 25 * 1024 = 25600 |
| 10 x 10 grid, word length 6 | Up to 100 * 4^6 = 100 * 4096 = 409600 |
Pattern observation: Operations grow exponentially with word length and linearly with grid size.
Time Complexity: O(m * n * 4^k)
This means the time grows quickly with the word length and also depends on the grid size.
[X] Wrong: "The search only checks each cell once, so it is O(m * n)."
[OK] Correct: The search explores many paths recursively for each character, causing exponential growth with word length, not just linear with grid size.
Understanding this complexity helps you explain how backtracking explores many possibilities and why it can be slow for long words or big grids.
"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 role
Backtracking tries all possible paths in the grid to find the target word by moving in allowed directions.Step 2: Eliminate other options
Sorting, counting, or replacing characters are unrelated to searching paths for the word.Final Answer:
To explore all possible paths to find the word -> Option BQuick Check:
Backtracking = Explore paths [OK]
- Thinking backtracking sorts or modifies the grid
- Confusing backtracking with simple search
- Assuming backtracking counts words instead of searching
Solution
Step 1: Check method parameters
The method needs the board (2D char array), the word, current index in word, and current position (row, col) to explore.Step 2: Check return type
Backtracking returns boolean to indicate if word is found along this path.Final Answer:
boolean backtrack(char[][] board, String word, int index, int row, int col) -> Option AQuick Check:
Correct signature = boolean backtrack(char[][] board, String word, int index, int row, int col) [OK]
- Using 1D array instead of 2D for board
- Wrong return type like int or String
- Missing index or position parameters
[['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E']]
and the word
"ABCCED", what will the backtracking function return?Solution
Step 1: Trace the word in the grid
The word "ABCCED" can be found by path: A(0,0) -> B(0,1) -> C(0,2) -> C(1,2) -> E(2,2) -> D(2,1).Step 2: Backtracking confirms path exists
Since the path exists without revisiting cells, backtracking returns true.Final Answer:
true -> Option DQuick Check:
Word found = true [OK]
- Assuming word is not found without checking all directions
- Confusing similar letters in different positions
- Ignoring backtracking's ability to explore multiple paths
if (row < 0 || col < 0 || row >= board.length || col >= board[0].length || board[row][col] != word.charAt(index)) {
return false;
}What is the main issue if we forget to mark visited cells during recursion?
Solution
Step 1: Understand visited marking role
Marking visited cells prevents revisiting the same cell in the current path, avoiding cycles.Step 2: Consequence of missing visited marking
Without marking, recursion may revisit cells endlessly, causing infinite loops or stack overflow.Final Answer:
The function may revisit the same cell causing infinite loops -> Option AQuick Check:
Missing visited mark = infinite loops [OK]
- Assuming no visited marking is safe
- Confusing out-of-bound checks with visited logic
- Thinking missing visited causes exceptions instead of loops
"SEE" exists in the grid:[['A','B','C','E'], ['S','F','E','S'], ['A','D','E','E']]
Using backtracking, which approach correctly handles multiple possible paths and avoids revisiting cells?
Solution
Step 1: Understand visited marking with backtracking
Using a boolean visited array allows marking cells as visited during recursion and unmarking them after exploring all paths from that cell.Step 2: Evaluate other options
Modifying board permanently breaks original data, searching only right misses paths, and limiting recursion depth does not solve revisiting.Final Answer:
Use a boolean visited[][] array to mark cells during recursion and backtrack by unmarking after recursion returns -> Option CQuick Check:
Visited array + backtrack unmark = correct approach [OK]
- Permanently changing board characters
- Ignoring directions other than right
- Using recursion limits instead of visited marking
Ready to prove it?
Pass the test and this pattern moves unknown
