本題有點複雜,需要結合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;
}