67. Word Search
Return true if word can be formed from letters of sequentially adjacent cells (up/down/left/right) in board. A cell may not be used twice in one word.
Example 1
Input:
board = [["C","A","T"],["X","R","S"],["O","D","E"]], word = "CAR"Output:
trueExample 2
Input:
board = [["C","A","T"],["X","R","S"],["O","D","E"]], word = "CATS"Output:
trueHint 1
Try every cell as a start and DFS letter by letter.
Hint 2
Temporarily overwrite a cell to mark it as used, and restore it when you backtrack.
Approach 1: DFS backtracking ✅
Mark/unmark cells along the path.
⏱ Time O(m · n · 4ᴸ)💾 Space O(L)
Reference solution for DFS backtracking (time O(m · n · 4ᴸ), space O(L)). Each solution passes every test in all four languages.
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
m, n = len(board), len(board[0])
def dfs(r, c, k):
if k == len(word):
return True
if r < 0 or c < 0 or r >= m or c >= n or board[r][c] != word[k]:
return False
board[r][c] = '#' # mark as used on this path
found = dfs(r + 1, c, k + 1) or dfs(r - 1, c, k + 1) or dfs(r, c + 1, k + 1) or dfs(r, c - 1, k + 1)
board[r][c] = word[k] # restore (backtrack)
return found
return any(dfs(r, c, 0) for r in range(m) for c in range(n))class Solution {
public boolean exist(char[][] board, String word) {
for (int r = 0; r < board.length; r++)
for (int c = 0; c < board[0].length; c++)
if (dfs(board, word, r, c, 0)) return true;
return false;
}
private boolean dfs(char[][] b, String w, int r, int c, int k) {
if (k == w.length()) return true;
if (r < 0 || c < 0 || r >= b.length || c >= b[0].length || b[r][c] != w.charAt(k)) return false;
b[r][c] = '#';
boolean found = dfs(b, w, r + 1, c, k + 1) || dfs(b, w, r - 1, c, k + 1) || dfs(b, w, r, c + 1, k + 1) || dfs(b, w, r, c - 1, k + 1);
b[r][c] = w.charAt(k);
return found;
}
}class Solution {
bool dfs(vector<vector<char>>& b, const string& w, int r, int c, int k) {
if (k == (int)w.size()) return true;
if (r < 0 || c < 0 || r >= (int)b.size() || c >= (int)b[0].size() || b[r][c] != w[k]) return false;
b[r][c] = '#';
bool found = dfs(b, w, r + 1, c, k + 1) || dfs(b, w, r - 1, c, k + 1) || dfs(b, w, r, c + 1, k + 1) || dfs(b, w, r, c - 1, k + 1);
b[r][c] = w[k];
return found;
}
public:
bool exist(vector<vector<char>>& board, string word) {
for (int r = 0; r < (int)board.size(); r++)
for (int c = 0; c < (int)board[0].size(); c++)
if (dfs(board, word, r, c, 0)) return true;
return false;
}
};function exist(board, word) {
const m = board.length, n = board[0].length;
const dfs = (r, c, k) => {
if (k === word.length) return true;
if (r < 0 || c < 0 || r >= m || c >= n || board[r][c] !== word[k]) return false;
board[r][c] = '#';
const found = dfs(r + 1, c, k + 1) || dfs(r - 1, c, k + 1) || dfs(r, c + 1, k + 1) || dfs(r, c - 1, k + 1);
board[r][c] = word[k];
return found;
};
for (let r = 0; r < m; r++) for (let c = 0; c < n; c++) if (dfs(r, c, 0)) return true;
return false;
}Try solving it yourself first. Interviewers care more about how you explain the approach than about the finished code.
Watch the core idea of this problem step by step. Change the input and press Visualize.
Explained in the lesson Recursion & Backtracking.
Run your code to see results here.