Back to Backtracking
Word Search
Word Search
🧩 Problem Statement
Given an m x n grid of characters board and a string word, return true if word exists in the grid.
The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.
🔹 Example 1:
Input:
board = [
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
], word = "ABCCED"
Output:
true
🔹 Example 2:
Input:
board = [
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
], word = "SEE"
Output:
true
🔍 Approaches
1. Backtracking (DFS)
We need to find if there is any path in the grid that spells out the word.
- Iterate through every cell
(r, c)in the grid. - If
board[r][c]matches the first letter ofword, start a DFS traversal from there. - DFS(r, c, index):
- Base Case: If
index == word.length(), we found the word. Returntrue. - Boundary Check: If
r, cout of bounds orboard[r][c]doesn't matchword[index], returnfalse. - Mark Visited: Temporarily change
board[r][c]to a special char (e.g.,#) to avoid cycles. - Recurse: Check all 4 directions:
(r+1, c), (r-1, c), (r, c+1), (r, c-1). - Backtrack: Restore
board[r][c]to original char. - Return result of recursion.
⏳ Time & Space Complexity
- Time Complexity: $O(M \cdot N \cdot 3^L)$, where $L$ is length of word. We explore 3 directions (excluding where we came from) for each step in
word. - Space Complexity: $O(L)$ for recursion stack.
🚀 Code Implementations
C++
#include <vector>
#include <string>
using namespace std;
class Solution {
public:
bool exist(vector<vector<char>>& board, string word) {
int m = board.size();
int n = board[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == word[0] && dfs(board, i, j, word, 0)) {
return true;
}
}
}
return false;
}
private:
bool dfs(vector<vector<char>>& board, int i, int j, const string& word, int index) {
if (index == word.length()) return true;
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() || board[i][j] != word[index]) {
return false;
}
char temp = board[i][j];
board[i][j] = '#'; // Mark visited
bool found = dfs(board, i + 1, j, word, index + 1) ||
dfs(board, i - 1, j, word, index + 1) ||
dfs(board, i, j + 1, word, index + 1) ||
dfs(board, i, j - 1, word, index + 1);
board[i][j] = temp; // Backtrack
return found;
}
};
Python
from typing import List
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
rows, cols = len(board), len(board[0])
def dfs(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] = '#' # Mark visited
found = (dfs(r + 1, c, index + 1) or
dfs(r - 1, c, index + 1) or
dfs(r, c + 1, index + 1) or
dfs(r, c - 1, index + 1))
board[r][c] = temp # Backtrack
return found
for i in range(rows):
for j in range(cols):
if board[i][j] == word[0] and dfs(i, j, 0):
return True
return False
Java
class Solution {
public boolean exist(char[][] board, String word) {
int m = board.length;
int n = board[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == word.charAt(0) && dfs(board, i, j, word, 0)) {
return true;
}
}
}
return false;
}
private boolean dfs(char[][] board, int i, int j, String word, int index) {
if (index == word.length()) return true;
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(index)) {
return false;
}
char temp = board[i][j];
board[i][j] = '#'; // Mark visited
boolean found = dfs(board, i + 1, j, word, index + 1) ||
dfs(board, i - 1, j, word, index + 1) ||
dfs(board, i, j + 1, word, index + 1) ||
dfs(board, i, j - 1, word, index + 1);
board[i][j] = temp; // Backtrack
return found;
}
}
🌍 Real-World Analogy
Boggle Game:
You are searching for a word in a grid of letter dice. You can move to any neighbor, but you can't reuse a die you've already touched in the current word chain.
🎯 Summary
✅ DFS: Explore path depth-first.
✅ Backtracking: Unmark visited cells to allow other paths to use them.
Solution Code
O(n) TimeO(1) Space
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
bool exist(vector<vector<char>> &board, string word) {
int m = board.size();
int n = board[0].size();
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (board[i][j] == word[0] && dfs(board, i, j, word, 0)) {
return true;
}
}
}
return false;
}
private:
bool dfs(vector<vector<char>> &board, int i, int j, const string &word,
int index) {
if (index == word.length())
return true;
if (i < 0 || i >= board.size() || j < 0 || j >= board[0].size() ||
board[i][j] != word[index]) {
return false;
}
char temp = board[i][j];
board[i][j] = '#'; // Mark visited
bool found = dfs(board, i + 1, j, word, index + 1) ||
dfs(board, i - 1, j, word, index + 1) ||
dfs(board, i, j + 1, word, index + 1) ||
dfs(board, i, j - 1, word, index + 1);
board[i][j] = temp; // Backtrack
return found;
}
};
int main() {
Solution sol;
vector<vector<char>> board = {
{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}};
cout << "Exist ABCCED: " << sol.exist(board, "ABCCED") << endl; // Expect 1
cout << "Exist SEE: " << sol.exist(board, "SEE") << endl; // Expect 1
cout << "Exist ABCB: " << sol.exist(board, "ABCB") << endl; // Expect 0
return 0;
}
SYSTEM STABLEUTF-8 • STATIC_RENDER