原题链接
方法1(略)
遍历 words 数组,挨个单词去 board 里面找
方法2:Trie树
将 words 数组中的所有单词构建成一颗 Trie 树,对 board 数组进行一次DFS
代码中的 Trie 实现 在这里
public List<String> findWords(char[][] board, String[] words) {
Trie trie = new Trie();
for(String word : words) {//构建Trie树
trie.insert(word);
}
//使用set存储最终结果,去重
Set<String> result = new HashSet<>();
int row = board.length;
int col = board[0].length;
boolean[][] visited = new boolean[row][col];//表示board中的每个字符是否访问过
//遍历 board
for(int i = 0;i < row;i++) {
for(int j = 0;j < col;j++) {
//以当前字符进行dfs
dfs(board, i, j, trie.root, visited, "", result);
}
}
return new ArrayList<String>(result);
}
private void dfs(char[][] board, int i, int j, TrieNode cur, boolean[][] visited, String tmp, Set<String> result) {
//边界处理
if(i < 0 || j < 0 || i >= board.length || j >= board[0].length || visited[i][j]) return ;
cur = cur.children[board[i][j] - 'a'];
if(cur == null) return;//当前字符和字典树不匹配
//当前字符和字典树匹配的话
tmp = tmp + cur.val;//记录当前节点的值
//匹配到单词了
if(cur.isWord) result.add(tmp);
visited[i][j] = true;//标记为 访问
//从当前字符向四周回溯
dfs(board, i - 1, j, cur, visited, tmp, result);//向上
dfs(board, i + 1, j, cur, visited, tmp, result);//向下
dfs(board, i, j - 1, cur, visited, tmp, result);//向左
dfs(board, i, j + 1, cur, visited, tmp, result);//向右
//同一个单元格内的字母在一个单词中不允许被重复使用(所以限制的是同一次dfs过程中不能重复使用)
visited[i][j] = false;//最后要回退,因为下一个单词可以使用到上一个单词中的的字符
}