Word Search in Grid Using Backtracking in DSA C++ - Time & Space Complexity
We want to understand how the time needed to find a word in a grid grows as the grid and word sizes increase.
How does the search effort change when the grid or word gets bigger?
Analyze the time complexity of the following code snippet.
bool backtrack(vector<vector<char>>& board, string& word, int i, int j, int index) {
if (index == word.size()) return true;
if (i < 0 || j < 0 || i >= board.size() || j >= board[0].size() || board[i][j] != word[index]) return false;
char temp = board[i][j];
board[i][j] = '#';
bool 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;
}
bool exist(vector<vector<char>>& board, string word) {
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board[0].size(); j++) {
if (backtrack(board, word, i, j, 0)) return true;
}
}
return false;
}
This code tries to find a word in a 2D grid by exploring all possible paths using backtracking.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive backtracking calls exploring up to 4 directions for each letter in the word.
- How many times: For each cell in the grid (m x n), it may start a search that explores up to 4 choices per letter in the word (length k).
As the grid size (m x n) and word length (k) grow, the search tries many paths.
| 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: The operations grow very fast because for each letter, up to 4 directions are explored, leading to exponential growth with word length.
Time Complexity: O(m * n * 4^k)
This means the time grows quickly with the word length, as each letter can lead to 4 new paths, and we try starting from every cell.
[X] Wrong: "The search only takes time proportional to the grid size (m * n)."
[OK] Correct: Because for each cell, the search explores many possible paths for the word letters, causing exponential growth with word length, not just grid size.
Understanding this complexity helps you explain why backtracking can be slow and when it is suitable, showing your grasp of algorithm behavior in real problems.
"What if we limited the search to only move right and down instead of all 4 directions? How would the time complexity change?"
Practice
Word Search in Grid problem?Solution
Step 1: Understand backtracking role
Backtracking tries all possible paths in the grid to find the word by moving in allowed directions and undoing moves if they don't lead to a solution.Step 2: Eliminate other 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 in the grid -> Option AQuick Check:
Backtracking = Explore paths [OK]
- Thinking backtracking sorts or modifies the grid
- Confusing backtracking with simple searching
- Ignoring the undo step in backtracking
Solution
Step 1: Understand grid indexing
Grid rows and columns start at 0, so valid indices are from 0 to rows-1 and 0 to cols-1.Step 2: Check boundary condition
if (row >= 0 && row < rows && col >= 0 && col < cols) correctly checks if row and col are within these ranges using && (and) operator.Final Answer:
if (row >= 0 && row < rows && col >= 0 && col < cols) -> Option CQuick Check:
Boundary check = if (row >= 0 && row < rows && col >= 0 && col < cols) [OK]
- Using > 0 instead of >= 0 excludes first row/column
- Using || instead of && allows invalid indices
- Checking only (0,0) cell
char grid[3][3] = {{'A','B','C'},{'D','E','F'},{'G','H','I'}};
string word = "BE";
// Assume function exist: bool exist(char grid[][], string word)
cout << (exist(grid, word) ? "Found" : "Not Found") << endl;Assuming
exist uses backtracking correctly.Solution
Step 1: Analyze grid and word
The grid is:
A B C
D E F
G H I
The word is "BE".Step 2: Check if "BE" can be formed
Starting at 'B' (0,1), next letter 'E' must be adjacent (up, down, left, right). Adjacent cells to 'B' are 'A'(0,0), 'C'(0,2), 'E'(1,1). 'E' is adjacent, so path B->E exists.Step 3: Confirm backtracking finds the word
Backtracking will find "BE" successfully.Final Answer:
Found -> Option AQuick Check:
Word "BE" exists in grid = Found [OK]
- Ignoring adjacency rules
- Assuming diagonal moves allowed (usually not)
- Confusing output with error
bool backtrack(int r, int c, int index) {
if (index == word.length()) return true;
if (r < 0 || r >= rows || c < 0 || c >= cols) return false;
if (grid[r][c] != word[index]) return false;
grid[r][c] = '#';
bool found = backtrack(r+1, c, index+1) || backtrack(r-1, c, index+1) || backtrack(r, c+1, index+1) || backtrack(r, c-1, index+1);
return found;
}Solution
Step 1: Understand backtracking marking
The code marks visited cells by setting grid[r][c] = '#'.Step 2: Check if grid is restored after recursion
After recursive calls, the original character should be restored to allow other paths. This code does not restore it.Step 3: Identify the bug
Missing restoration causes wrong results or blocks other paths.Final Answer:
Missing restoring grid[r][c] after recursion -> Option DQuick Check:
Restore grid after recursion = Fix bug [OK]
- Not restoring visited cells
- Wrong base case logic
- Incorrect boundary conditions
char grid[4][4] = {
{'C','A','T','F'},
{'B','G','E','S'},
{'I','T','A','E'},
{'S','E','R','T'}
};Which of the following words can be found using backtracking moving only up, down, left, or right?
Select the correct option.
Solution
Step 1: Check "CATS"
"CATS" starts at (0,0) 'C', next 'A' at (0,1), next 'T' at (0,2), but no adjacent 'S' to 'T' at (0,2). Adjacent: 'A'(0,1), 'F'(0,3), 'E'(1,2). No path exists.Step 2: Check "TEA"
"TEA" letters: T, E, A.
Possible path: (2,1) 'T' -> (3,1) 'E' -> (2,2) 'A' ? From 'E'(3,1) to 'A'(2,2) is diagonal, invalid.
Try other 'T's: (0,2) 'T' -> (1,2) 'E' down -> (2,2) 'A' down. Valid path.Step 3: Check "FEST" and "BAT"
"FEST" letters not found in order with adjacency.
"BAT" letters: B(1,0), A(2,2), T(0,2) no continuous path.Final Answer:
"TEA" -> Option BQuick Check:
Check adjacency for each word = "TEA" found [OK]
- Assuming diagonal moves allowed
- Not checking letter order carefully
- Ignoring multiple occurrences of letters
Ready to prove it?
Pass the test and this pattern moves unknown
