🧠
Brute Force (Search Each Word Individually)
💡 This approach is the most straightforward: for each word, search the board using backtracking. It is slow but helps understand the problem's core mechanics.
Intuition
Try to find each word on the board by starting from every cell and exploring all paths recursively.
Algorithm
- For each word in the list:
- For each cell in the board:
- Use DFS to check if the word can be formed starting from that cell.
- If found, add the word to the result list.
💡 The nested loops and recursive DFS are easy to get lost in; focusing on one word at a time clarifies the process.
from typing import List
def exist(board: List[List[str]], word: str) -> bool:
rows, cols = len(board), len(board[0])
visited = [[False]*cols for _ in range(rows)]
def dfs(r, c, idx):
if idx == len(word):
return True
if r < 0 or r >= rows or c < 0 or c >= cols or visited[r][c] or board[r][c] != word[idx]:
return False
visited[r][c] = True
res = (dfs(r+1, c, idx+1) or dfs(r-1, c, idx+1) or dfs(r, c+1, idx+1) or dfs(r, c-1, idx+1))
visited[r][c] = False
return res
for r in range(rows):
for c in range(cols):
if dfs(r, c, 0):
return True
return False
def findWords(board: List[List[str]], words: List[str]) -> List[str]:
result = []
for word in words:
if exist(board, word):
result.append(word)
return result
# Driver code
if __name__ == '__main__':
board = [
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
words = ['oath','pea','eat','rain']
print(findWords(board, words))
Line Notes
def exist(board: List[List[str]], word: str) -> bool:Defines a helper function to check if a single word exists on the board
visited = [[False]*cols for _ in range(rows)]Tracks visited cells to avoid reusing letters in the same word path
if idx == len(word):Base case: all characters matched successfully
visited[r][c] = TrueMark current cell as visited before exploring neighbors
visited[r][c] = FalseBacktrack by unmarking the cell after exploring
for r in range(rows):Try starting DFS from every cell in the board
if dfs(r, c, 0):If DFS finds the word starting at this cell, return True
for word in words:Check each word independently, leading to high time complexity
import java.util.*;
public class WordSearchBrute {
private static boolean exist(char[][] board, String word) {
int rows = board.length, cols = board[0].length;
// For each cell, try DFS with fresh visited array
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
boolean[][] visited = new boolean[rows][cols];
if (dfs(board, word, r, c, 0, visited)) {
return true;
}
}
}
return false;
}
private static boolean dfs(char[][] board, String word, int r, int c, int idx, boolean[][] visited) {
if (idx == word.length()) return true;
if (r < 0 || r >= board.length || c < 0 || c >= board[0].length || visited[r][c] || board[r][c] != word.charAt(idx))
return false;
visited[r][c] = true;
boolean res = dfs(board, word, r + 1, c, idx + 1, visited) ||
dfs(board, word, r - 1, c, idx + 1, visited) ||
dfs(board, word, r, c + 1, idx + 1, visited) ||
dfs(board, word, r, c - 1, idx + 1, visited);
visited[r][c] = false;
return res;
}
public static List<String> findWords(char[][] board, String[] words) {
List<String> result = new ArrayList<>();
for (String word : words) {
if (exist(board, word)) {
result.add(word);
}
}
return result;
}
public static void main(String[] args) {
char[][] board = {
{'o','a','a','n'},
{'e','t','a','e'},
{'i','h','k','r'},
{'i','f','l','v'}
};
String[] words = {"oath", "pea", "eat", "rain"};
System.out.println(findWords(board, words));
}
}
Line Notes
private static boolean exist(char[][] board, String word)Checks if a single word exists on the board by trying DFS from every cell with fresh visited array
for (int r = 0; r < rows; r++)Iterate over all rows as starting points
for (int c = 0; c < cols; c++)Iterate over all columns as starting points
boolean[][] visited = new boolean[rows][cols];Create a fresh visited array for each DFS to avoid contamination
if (dfs(board, word, r, c, 0, visited))If DFS finds the word starting at this cell, return true
private static boolean dfs(char[][] board, String word, int r, int c, int idx, boolean[][] visited)DFS helper to check if word exists starting at (r,c)
if (idx == word.length()) return true;Base case: all characters matched
visited[r][c] = true;Mark cell visited before recursive calls
visited[r][c] = false;Backtrack by unmarking after recursion
for (String word : words)Check each word independently, leading to high time complexity
#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
using namespace std;
bool dfs(vector<vector<char>>& board, string& word, int r, int c, int idx, vector<vector<bool>>& visited) {
if (idx == word.size()) return true;
int rows = board.size(), cols = board[0].size();
if (r < 0 || r >= rows || c < 0 || c >= cols || visited[r][c] || board[r][c] != word[idx])
return false;
visited[r][c] = true;
bool res = dfs(board, word, r+1, c, idx+1, visited) ||
dfs(board, word, r-1, c, idx+1, visited) ||
dfs(board, word, r, c+1, idx+1, visited) ||
dfs(board, word, r, c-1, idx+1, visited);
visited[r][c] = false;
return res;
}
bool exist(vector<vector<char>>& board, string& word) {
int rows = board.size(), cols = board[0].size();
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
vector<vector<bool>> visited(rows, vector<bool>(cols, false));
if (dfs(board, word, r, c, 0, visited))
return true;
}
}
return false;
}
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
vector<string> result;
for (auto& word : words) {
if (exist(board, word)) {
result.push_back(word);
}
}
return result;
}
int main() {
vector<vector<char>> board = {
{'o','a','a','n'},
{'e','t','a','e'},
{'i','h','k','r'},
{'i','f','l','v'}
};
vector<string> words = {"oath", "pea", "eat", "rain"};
vector<string> res = findWords(board, words);
for (auto& w : res) cout << w << " ";
cout << endl;
return 0;
}
Line Notes
bool dfs(vector<vector<char>>& board, string& word, int r, int c, int idx, vector<vector<bool>>& visited)DFS helper to check if word exists starting at (r,c)
if (idx == word.size()) return true;All characters matched base case
visited[r][c] = true;Mark cell visited before recursion
visited[r][c] = false;Backtrack by unmarking after recursion
for (int r = 0; r < rows; r++)Try all cells as starting points
for (int c = 0; c < cols; c++)Try all cells as starting points
vector<vector<bool>> visited(rows, vector<bool>(cols, false));Create fresh visited array for each DFS call
for (auto& word : words)Check each word independently
if (dfs(board, word, r, c, 0, visited))If DFS finds word, return true
function exist(board, word) {
const rows = board.length, cols = board[0].length;
function dfs(r, c, idx, visited) {
if (idx === word.length) return true;
if (r < 0 || r >= rows || c < 0 || c >= cols || visited[r][c] || board[r][c] !== word[idx])
return false;
visited[r][c] = true;
const res = dfs(r+1, c, idx+1, visited) || dfs(r-1, c, idx+1, visited) || dfs(r, c+1, idx+1, visited) || dfs(r, c-1, idx+1, visited);
visited[r][c] = false;
return res;
}
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
const visited = Array.from({length: rows}, () => Array(cols).fill(false));
if (dfs(r, c, 0, visited)) return true;
}
}
return false;
}
function findWords(board, words) {
const result = [];
for (const word of words) {
if (exist(board, word)) {
result.push(word);
}
}
return result;
}
// Driver code
const board = [
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
];
const words = ['oath','pea','eat','rain'];
console.log(findWords(board, words));
Line Notes
function exist(board, word)Helper function to check if a single word exists
for (let r = 0; r < rows; r++)Try all rows as starting points
for (let c = 0; c < cols; c++)Try all columns as starting points
const visited = Array.from({length: rows}, () => Array(cols).fill(false));Create fresh visited array for each DFS call
if (dfs(r, c, 0, visited)) return true;If DFS finds the word starting at this cell, return true
function dfs(r, c, idx, visited)DFS helper to check if word exists starting at (r,c)
if (idx === word.length) return true;Base case: all characters matched
visited[r][c] = true;Mark cell visited before recursive calls
visited[r][c] = false;Backtrack by unmarking after recursion
for (const word of words)Check each word independently
TimeO(N * 4^L * W) where N = number of cells, L = max word length, W = number of words
SpaceO(L) for recursion stack and visited array
For each word, we try starting from each cell and explore up to 4 directions recursively for length L, repeated for W words.
💡 For a 4x4 board and 10 words of length 5, this could mean millions of operations, which is impractical.
Interview Verdict: TLE / Use only to introduce problem and brute force concept
This approach is too slow for large inputs but is essential to understand before optimizing.