Trie-guided backtracking
Time O(cells × 4 × 3^(L−1)) worst case, much less with pruning Space O(total characters)Build a trie storing each word at its end node. From every cell, DFS: follow the child for the cell's letter, record and clear a word if one ends here, mark the cell used, recurse in four directions, then restore it.
import java.util.*;
class Solution {
private static class Node {
Node[] next = new Node[26];
String word;
}
public List<String> findWords(char[][] board, String[] words) {
Node root = new Node();
for (String w : words) {
Node n = root;
for (char c : w.toCharArray()) {
if (n.next[c - 'a'] == null) n.next[c - 'a'] = new Node();
n = n.next[c - 'a'];
}
n.word = w;
}
List<String> out = new ArrayList<>();
for (int r = 0; r < board.length; r++)
for (int c = 0; c < board[0].length; c++) dfs(board, r, c, root, out);
return out;
}
private void dfs(char[][] b, int r, int c, Node parent, List<String> out) {
if (r < 0 || c < 0 || r >= b.length || c >= b[0].length) return;
char ch = b[r][c];
if (ch == '#') return;
Node n = parent.next[ch - 'a'];
if (n == null) return; // no word continues this way: prune
if (n.word != null) { out.add(n.word); n.word = null; }
b[r][c] = '#';
dfs(b, r + 1, c, n, out);
dfs(b, r - 1, c, n, out);
dfs(b, r, c + 1, n, out);
dfs(b, r, c - 1, n, out);
b[r][c] = ch;
}
}Verdict: The standard solution.