【重温经典】单词搜索II

方法1:朴素版DFS
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
int m, n;
List<String> res = new ArrayList<>();
public List<String> findWords(char[][] board, String[] words) {
this.m = board.length;
this.n = board[0].length;
for (String word : words) {
if (exist(board, word)) res.add(word);
}
return res;
}
public boolean exist(char[][] board, String word) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == word.charAt(0) && dfs(word, board, i, j, 0)) return true;
}
}
return false;
}
private boolean dfs(String word, char[][] board, int i, int j, int idx) {
if (i < 0 || i >= m || j < 0 || j >= n || board[i][j] != word.charAt(idx))
return false;
if (idx == word.length() - 1) return true;
char t = board[i][j];
board[i][j] = '#';
for (int d = 0; d < dx.length; d++) {
if (dfs(word, board, i + dx[d], j + dy[d], idx + 1)) {
board[i][j] = t;
return true;
}
}
board[i][j] = t;
return false;
}
方法2:Trie+DFS

- 也可以用
bool[m][n]
的访问数组标记某个字符的访问,替换掉board[i][j] = '#'
class TrieNode {
TrieNode[] next = new TrieNode[26];
String word;
}
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
int m, n;
List<String> res = new ArrayList<>();
public List<String> findWords(char[][] board, String[] words) {
this.m = board.length;
this.n = board[0].length;
TrieNode root = buildTrie(words);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dfs(board, i, j, root);
}
}
return res;
}
private void dfs(char[][] board, int i, int j, TrieNode p) {
if (i < 0 || i >= m || j < 0 || j >= n) return;
char c = board[i][j];
if (c == '#' || p.next[c - 'a'] == null) return;
p = p.next[c - 'a'];
if (p.word != null) {
res.add(p.word);
p.word = null;
}
board[i][j] = '#';
for (int d = 0; d < dx.length; d++) {
dfs(board, i + dx[d], j + dy[d], p);
}
board[i][j] = c;
}
private TrieNode buildTrie(String[] words) {
TrieNode root = new TrieNode();
for (String word : words) {
TrieNode cur = root;
for (char c : word.toCharArray()) {
if (cur.next[c - 'a'] == null) cur.next[c - 'a'] = new TrieNode();
cur = cur.next[c - 'a'];
}
cur.word = word;
}
return root;
}
方法3:Trie板子+DFS
static class _4th {
class TrieNode {
public TrieNode[] next = new TrieNode[26];
public String word = "";
public TrieNode() {
}
}
class Trie {
private TrieNode root;
public Trie() {
root = new TrieNode();
}
public void insert(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
if (node.next[c - 'a'] == null) {
node.next[c - 'a'] = new TrieNode();
}
node = node.next[c - 'a'];
}
node.word = word;
}
public boolean search(String word) {
TrieNode node = root;
for (char c : word.toCharArray()) {
if (node.next[c - 'a'] == null) return false;
node = node.next[c - 'a'];
}
return node.word.equals(word);
}
public boolean startsWith(String prefix) {
TrieNode node = root;
for (char c : prefix.toCharArray()) {
if (node.next[c - 'a'] == null) return false;
node = node.next[c - 'a'];
}
return true;
}
}
Set<String> res = new HashSet<String>();
int m, n;
int[] dx = {-1, 0, 1, 0};
int[] dy = {0, 1, 0, -1};
public List<String> findWords(char[][] board, String[] words) {
Trie trie = new Trie();
for (String word : words) {
trie.insert(word);
}
m = board.length;
n = board[0].length;
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dfs(board, visited, "", i, j, trie);
}
}
return new ArrayList<>(res);
}
public void dfs(char[][] board, boolean[][] visited, String str, int x, int y, Trie trie) {
if (x < 0 || x >= m || y < 0 || y >= n) return;
if (visited[x][y]) return;
str += board[x][y];
if (!trie.startsWith(str)) return;
if (trie.search(str)) {
res.add(str);
}
visited[x][y] = true;
for (int d = 0; d < dx.length; d++) {
dfs(board, visited, str, x + dx[d], y + dy[d], trie);
}
visited[x][y] = false;
}
}