Find Every Dictionary Word Traceable on a Letter Board
Solve this ProblemTest Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ board.length, board[0].length ≤ 6 - ◆
0 ≤ words.length ≤ 12, each word 1–10 uppercase letters - ◆
Each cell of the board may be used at most once per attempted word, and only horizontally/vertically adjacent cells may follow each other - ◆
Results are returned sorted in ascending (lexicographic) order for a stable, checkable answer
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
Approach & Solutions
Brute Force — Search the Whole Board Independently for Each Word
BruteTake each candidate word one at a time and run a complete, independent board search for it — scanning every cell as a possible starting point and exploring outward with backtracking, exactly like solving the single-word version of this problem from scratch. This is correct, but when two words share a prefix (like "HE" and "HELP"), the search for the second one re-walks the exact same opening letters the first search already confirmed, with absolutely no memory carried over between one word's search and the next.
O(words.length · rows · cols · 4^L)O(L)1class Solution {
2 public String[] findBoardWords(String[] board, String[] words) {
3 List<String> result = new ArrayList<>();
4 for (String word : words) {
5 if (exists(board, word)) {
6 result.add(word);
7 }
8 }
9 Collections.sort(result);
10 return result.toArray(new String[0]);
11 }
12
13 private boolean exists(String[] board, String word) {
14 int n = board.length, m = board[0].length();
15 boolean[][] visited = new boolean[n][m];
16 for (int r = 0; r < n; r++) {
17 for (int c = 0; c < m; c++) {
18 if (dfs(board, word, r, c, 0, visited)) return true;
19 }
20 }
21 return false;
22 }
23
24 private boolean dfs(String[] board, String word, int r, int c, int idx, boolean[][] visited) {
25 if (idx == word.length()) return true;
26 int n = board.length, m = board[0].length();
27 if (r < 0 || r >= n || c < 0 || c >= m || visited[r][c] || board[r].charAt(c) != word.charAt(idx)) return false;
28 visited[r][c] = true;
29 boolean found = dfs(board, word, r + 1, c, idx + 1, visited)
30 || dfs(board, word, r - 1, c, idx + 1, visited)
31 || dfs(board, word, r, c + 1, idx + 1, visited)
32 || dfs(board, word, r, c - 1, idx + 1, visited);
33 visited[r][c] = false;
34 return found;
35 }
36}Optimal — Build a Trie of All Words, Search the Board Once
OptimalInsert every word into a trie first, so words sharing a prefix share the same chain of trie nodes. Then walk the board exactly once with a single DFS pass, moving one letter at a time through both the board and the trie together, in lockstep. Whenever the trie node reached marks the end of a word, that word is found — and the search keeps going from that same node, since it may also be a prefix of a longer word still being searched for. Two words that begin the same way are confirmed using the same handful of board steps, not two separate full searches.
O(rows · cols · 4^L)O(total letters in words)1class Solution {
2 class TrieNode {
3 TrieNode[] children = new TrieNode[26];
4 String word = null;
5 }
6
7 public String[] findBoardWords(String[] board, String[] words) {
8 TrieNode root = new TrieNode();
9 for (String word : words) {
10 TrieNode node = root;
11 for (char ch : word.toCharArray()) {
12 int idx = ch - 'A';
13 if (node.children[idx] == null) node.children[idx] = new TrieNode();
14 node = node.children[idx];
15 }
16 node.word = word;
17 }
18 int n = board.length, m = board[0].length();
19 char[][] grid = new char[n][m];
20 for (int r = 0; r < n; r++) grid[r] = board[r].toCharArray();
21 List<String> result = new ArrayList<>();
22 boolean[][] visited = new boolean[n][m];
23 for (int r = 0; r < n; r++) {
24 for (int c = 0; c < m; c++) {
25 dfs(grid, r, c, root, visited, result);
26 }
27 }
28 Collections.sort(result);
29 return result.toArray(new String[0]);
30 }
31
32 private void dfs(char[][] grid, int r, int c, TrieNode node, boolean[][] visited, List<String> result) {
33 int n = grid.length, m = grid[0].length;
34 if (r < 0 || r >= n || c < 0 || c >= m || visited[r][c]) return;
35 int idx = grid[r][c] - 'A';
36 TrieNode next = node.children[idx];
37 if (next == null) return;
38 if (next.word != null) {
39 result.add(next.word);
40 next.word = null;
41 }
42 visited[r][c] = true;
43 dfs(grid, r + 1, c, next, visited, result);
44 dfs(grid, r - 1, c, next, visited, result);
45 dfs(grid, r, c + 1, next, visited, result);
46 dfs(grid, r, c - 1, next, visited, result);
47 visited[r][c] = false;
48 }
49}