题目:
Given a 2D board and a list of words from the dictionary, find all words in the board.
Each word must be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
For example,
Given words = ["oath","pea","eat","rain"] and board =
[
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
Return ["eat","oath"].
解答:
这题我原来是在word search I的基础上,用backtracking来做的,代码如下:
public boolean exist(char[][] board, String word, int i, int j, int pos, boolean[][] visited) {
if (pos == word.length()) return true;
if (i < 0 || i > board.length - 1 || j < 0 || j > board[i].length - 1) return false;
if (visited[i][j] || board[i][j] != word.charAt(pos)) return false;
visited[i][j] = true;
int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int k = 0; k < dir.length; k++) {
int x = i + dir[k][0], y = j + dir[k][1];
if (exist(board, word, x, y, pos + 1, visited)) {
return true;
}
}
visited[i][j] = false;
return false;
}
public boolean helper(char[][] board, String word) {
boolean[][] visited = new boolean[board.length][board[0].length];
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
if (exist(board, word, i, j, 0, visited)) {
return true;
}
}
}
return false;
}
public List<String> findWords(char[][] board, String[] words) {
List<String> result = new ArrayList<String>();
if (board == null || board.length == 0 || board[0].length == 0) return result;
for (String word : words) {
if (helper(board, word)) {
if (!result.contains(word)) {
result.add(word);
}
}
}
return result;
}
做完之后,结果运行是对的,但是TLE了,所以肯定是有更好的办法。在TLE的test case里,我看到是当prefix相同时,如果用backtracking那么会不断地扫同一个位置的prefix,非常的冗余,那么怎么把prefix提取出来只扫一次呢?一个很好的办法就是反过来,用trie树先把单词存起来,然后扫board,扫board的时候用trie树中的可能出现的单词作为限制条件,那么当扫到一个trie中结尾存在的单词时,把它存进result中去。代码如下:
class TrieNode {
TrieNode[] next = new TrieNode[26];
String word;
}
public TrieNode buildTrie(String[] words) {
TrieNode root = new TrieNode();
for (String word : words) {
TrieNode p = root;
for (char c : word.toCharArray()) {
int i = c - 'a';
if (p.next[i] == null) p.next[i] = new TrieNode();
p = p.next[i];
}
p.word = word;
}
return root;
}
public void dfs(List<String> result, char[][] board, TrieNode p, int i, int j) {
char c = board[i][j];
if (c == '#' || p.next[c - 'a'] == null) return;
p = p.next[c - 'a'];
if (p.word != null) {
result.add(p.word);
p.word = null; //去重
}
board[i][j] = '#';
int[][] dir = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int k = 0; k < dir.length; k++) {
int x = i + dir[k][0], y = j + dir[k][1];
if (x < 0 || x > board.length - 1 || y < 0 || y > board[i].length - 1) continue;
dfs(result, board, p, x, y);
}
board[i][j] = c;
}
public List<String> findWords(char[][] board, String[] words) {
List<String> result = new ArrayList<String>();
if (board == null || board.length == 0 || board[0].length == 0) return result;
TrieNode root = buildTrie(words);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
dfs(result, board, root, i, j);
}
}
return result;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。