本题有点复杂,需要结合leetCode来看,只当其中一个答案来看即可,不然会云里雾里。
1. 题目
- 单词搜索二:给定一个二维网格board和一个字典中的单词列表words,找出所有同时在二位网格和字典中出现的单词。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中相邻单元格式那些水平相邻或者垂直相邻的单元格,同一个单元格中的字母不允许在同一个单词内多次出现。
https://leetcode-cn.com/problems/word-search-ii/
2. 基本知识
本题还是用的Trie的知识。
3. 算法题解
3.1 单词搜索二
给定一个二维网格board和一个字典中的单词列表words,找出所有同时在二位网格和字典中出现的单词。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中相邻单元格式那些水平相邻或者垂直相邻的单元格,同一个单元格中的字母不允许在同一个单词内多次出现。
图后补
假设所有字母都是小写,限定范围,再解题。
回溯法:使用Tried树辅助
先将所有单词,分解成字符,组成Tried树,然后利用回溯法去判断,如果公共前缀不存在,则该单词不存在这个网络列表中。
Trie树的具体代码:
public class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (!node.contaionsKey(c)) {
node.put(c, node);
}
node = node.get(c);
node.setEnd();
}
}
public boolean startWith(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (node.contaionsKey(c)) {
node = node.get(c);
} else {
return false;
}
}
if (node != null)
return true;
else
return false;
}
public boolean sarch(String word) {
TrieNode node = root;
for (int i = 0; i < word.length(); i++) {
char c = word.charAt(i);
if (node.contaionsKey(c)) {
node = node.get(c);
} else {
node = null;
break;
}
}
if (node != null && node.isEnd()) {
return true;
} else {
return false;
}
}
}
本题的题解:
List<String> results = new ArrayList<>();
public List<String> findWords(String[] words, char[][] board) {
Trie trie = new Trie();
// 生成Tried树
for (String s : words) {
trie.insert(s);
}
//记下board的边界
int row = board.length;
int col = board[0].length;
// 使用一个数组来标记是否 已经使用过该节点
boolean[][] visted = new boolean[row][col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
dfs(board, visted, "", i, j, trie);
}
}
return results;
}
/**
* 遍历board,从Tried中查找是否存在,存在则加到列表中,否则不处理
*
* @param board 二维字符表格
* @param visted 是否使用过
* @param result 结果字符串,初始化为“”
* @param row
* @param col
* @param trie 字符组成的Tried树
*/
private void dfs(char[][] board, boolean[][] visted, String result, int row, int col, Trie trie) {
//遍历超出范围,终止
if (row >= board.length || col >= board[0].length)
return;
//组合前缀
result += board[row][col];
//成功查询到内容
if (trie.sarch(result))
results.add(result);
// 无公共前缀
if (!trie.startWith(result)) return;
//标记已使用
visted[row][col] = true;
//上一行
dfs(board, visted, result, row - 1, col, trie);
dfs(board, visted, result, row + 1, col, trie);
dfs(board, visted, result, row, col - 1, trie);
dfs(board, visted, result, row, col + 1, trie);
visted[row][col] = false;
}