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.
用Word Search I的解法会超市,因此得用trie来保存input的所有string,然后dfs遍历board来看当前的string是否存在于trie中。如果当前string不是trie中任意string的prefix,可以剪枝,不需要继续dfs下去。很好的题目,需要加强。
public class Solution {
public List<String> findWords(char[][] board, String[] words) {
List<String> res = new ArrayList<String>();
if (board == null || board.length == 0 || board[0].length == 0 || words == null || words.length == 0) {
return res;
}
boolean[][] visited = new boolean[board.length][board[0].length];
Set<String> noDuplicateInput = new HashSet<String>(Arrays.asList(words));
Trie trie = new Trie(noDuplicateInput);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
search(board, i, j, "", visited, trie, res);
}
}
return res;
}
private void search(char[][] board, int i, int j,
String str, boolean[][] visited, Trie trie, List<String> res) {
if (i < board.length && i >= 0 && j < board[0].length && j >= 0 && visited[i][j] == false) {
String newStr = str + board[i][j];
TrieNode endNode = trie.startWith(newStr);
if (endNode != null) {
if (endNode.leaf == true) {
res.add(newStr);
endNode.leaf = false; //avoid duplicate in result
}
visited[i][j] = true;
search(board, i+1, j, newStr, visited, trie, res);
search(board, i-1, j, newStr, visited, trie, res);
search(board, i, j+1, newStr, visited, trie, res);
search(board, i, j-1, newStr, visited, trie, res);
visited[i][j] = false;
}
}
}
class Trie {
TrieNode root;
public Trie(Set<String> strs) {
root = new TrieNode();
for (String str : strs) {
add(str);
}
}
//gets the last node in the tree that matches the str, return null if not match
public TrieNode startWith(String str) {
TrieNode res = null;
TrieNode curRoot = root;
for (int i = 0; i < str.length(); i++) {
if (curRoot.children != null && curRoot.children.get(str.charAt(i)) != null) {
if (i == str.length() - 1) {
res = curRoot.children.get(str.charAt(i));
}
curRoot = curRoot.children.get(str.charAt(i));
} else {
break;
}
}
return res;
}
public void add(String str) {
TrieNode curRoot = root;
for (int i = 0; i < str.length(); i++) {
if (curRoot.children == null) {
curRoot.children = new HashMap<Character, TrieNode>();
}
if (curRoot.children.get(str.charAt(i)) == null) {
curRoot.children.put(str.charAt(i), new TrieNode(str.charAt(i)));
}
if (i == str.length() - 1) {
curRoot.children.get(str.charAt(i)).leaf = true;
}
curRoot = curRoot.children.get(str.charAt(i));
}
}
public boolean contains(String str) {
TrieNode lastNode = startWith(str);
if (lastNode == null || lastNode.leaf == false) {
return false;
}
return true;
}
}
class TrieNode {
boolean leaf;
char ch;
Map<Character, TrieNode> children;
public TrieNode() { }
public TrieNode(char ch) {
this.ch = ch;
}
}
}