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"].
Note:
You may assume that all inputs are consist of lowercase letters a-z.
Solution:Backtrack + Trie
思路:
To optimize backtracking by stop backtracking earlier.
If the current candidate does not exist in all words' prefix, backtracking can be stopped immediately.
So: 先由words建Trie树,再dfs board,如果current candidate does not exist in all words' prefix, return
Time Complexity: O(N) Space Complexity: O(N)
Solution Code:
class Solution {
class TrieNode {
public TrieNode[] children = new TrieNode[26];
public boolean is_word;
}
private TrieNode buildTrie(String[] words) {
TrieNode root = new TrieNode();
for (String w: words) {
TrieNode cur = root;
for (int i = 0; i < w.length(); i++) {
char c = w.charAt(i);
if (cur.children[c - 'a'] == null) cur.children[c - 'a'] = new TrieNode();
cur = cur.children[c - 'a'];
}
cur.is_word = true;
}
return root;
}
private void dfs(char[][] board, int y, int x, TrieNode node, boolean[][] used, StringBuilder cur_res, List<String> result) {
if (y < 0 || x < 0 || y > board.length - 1 || x > board[0].length - 1) return;
if(used[y][x]) return;
if(node.children[board[y][x] - 'a'] == null) return; // essential trick
used[y][x] = true;
cur_res.append(board[y][x]);
node = node.children[board[y][x] - 'a'];
if(node.is_word) {
result.add(cur_res.toString());
node.is_word = false; // de-duplicate
}
dfs(board, y, x - 1, node, used, cur_res, result);
dfs(board, y, x + 1, node, used, cur_res, result);
dfs(board, y - 1, x, node, used, cur_res, result);
dfs(board, y + 1, x, node, used, cur_res, result);
cur_res.deleteCharAt(cur_res.length() - 1);
used[y][x] = false;
}
public List<String> findWords(char[][] board, String[] words) {
List<String> result = new ArrayList<>();
boolean[][] used = new boolean[board.length][board[0].length];
TrieNode root = buildTrie(words);
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board[0].length; x++) {
dfs(board, y, x, root, used, new StringBuilder(), result);
}
}
return result;
}
}