Given a 2D board and a list of words from the dictionary, find all words in the board.html
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.java
For example,
Given words = ["oath","pea","eat","rain"]
and board =node
[ ['o','a','a','n'], ['e','t','a','e'], ['i','h','k','r'], ['i','f','l','v'] ]
Return ["eat","oath"]
.python
Note:
You may assume that all inputs are consist of lowercase letters a-z
.數據結構
Hint:app
You would need to optimize your backtracking to pass the larger test. Could you stop backtracking earlier?ui
If the current candidate does not exist in all words' prefix, you could stop backtracking immediately. What kind of data structure could answer such query efficiently? Does a hash table work? Why or why not? How about a Trie? If you would like to learn how to implement a basic trie, please work on this problem: Implement Trie (Prefix Tree) first.this
79. Word Search 的拓展,79題是給一個單詞讓判斷是否存在,如今是給了一堆單詞,讓返回全部存在的單詞。spa
解法:仍是用79題的DFS方法,數據結構用字典樹Trie。code
有關字典樹的題還有:208. Implement Trie (Prefix Tree) , 211. Add and Search Word - Data structure design
Java:
public List<String> findWords(char[][] board, String[] words) { List<String> res = new ArrayList<>(); TrieNode root = buildTrie(words); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[0].length; j++) { dfs (board, i, j, root, res); } } return res; } public void dfs(char[][] board, int i, int j, TrieNode p, List<String> res) { char c = board[i][j]; if (c == '#' || p.next[c - 'a'] == null) return; p = p.next[c - 'a']; if (p.word != null) { // found one res.add(p.word); p.word = null; // de-duplicate } board[i][j] = '#'; if (i > 0) dfs(board, i - 1, j ,p, res); if (j > 0) dfs(board, i, j - 1, p, res); if (i < board.length - 1) dfs(board, i + 1, j, p, res); if (j < board[0].length - 1) dfs(board, i, j + 1, p, res); board[i][j] = c; } public TrieNode buildTrie(String[] words) { TrieNode root = new TrieNode(); for (String w : words) { TrieNode p = root; for (char c : w.toCharArray()) { int i = c - 'a'; if (p.next[i] == null) p.next[i] = new TrieNode(); p = p.next[i]; } p.word = w; } return root; } class TrieNode { TrieNode[] next = new TrieNode[26]; String word; }
Python:
class TrieNode(object): # Initialize your data structure here. def __init__(self): self.is_string = False self.leaves = {} # Inserts a word into the trie. def insert(self, word): cur = self for c in word: if not c in cur.leaves: cur.leaves[c] = TrieNode() cur = cur.leaves[c] cur.is_string = True class Solution(object): def findWords(self, board, words): """ :type board: List[List[str]] :type words: List[str] :rtype: List[str] """ visited = [[False for j in xrange(len(board[0]))] for i in xrange(len(board))] result = {} trie = TrieNode() for word in words: trie.insert(word) for i in xrange(len(board)): for j in xrange(len(board[0])): if self.findWordsRecu(board, trie, 0, i, j, visited, [], result): return True return result.keys() def findWordsRecu(self, board, trie, cur, i, j, visited, cur_word, result): if not trie or i < 0 or i >= len(board) or j < 0 or j >= len(board[0]) or visited[i][j]: return if board[i][j] not in trie.leaves: return cur_word.append(board[i][j]) next_node = trie.leaves[board[i][j]] if next_node.is_string: result["".join(cur_word)] = True visited[i][j] = True self.findWordsRecu(board, next_node, cur + 1, i + 1, j, visited, cur_word, result) self.findWordsRecu(board, next_node, cur + 1, i - 1, j, visited, cur_word, result) self.findWordsRecu(board, next_node, cur + 1, i, j + 1, visited, cur_word, result) self.findWordsRecu(board, next_node, cur + 1, i, j - 1, visited, cur_word, result) visited[i][j] = False cur_word.pop()
C++:
class Solution { public: struct TrieNode { TrieNode *child[26]; string str; TrieNode() : str("") { for (auto &a : child) a = NULL; } }; struct Trie { TrieNode *root; Trie() : root(new TrieNode()) {} void insert(string s) { TrieNode *p = root; for (auto &a : s) { int i = a - 'a'; if (!p->child[i]) p->child[i] = new TrieNode(); p = p->child[i]; } p->str = s; } }; vector<string> findWords(vector<vector<char> >& board, vector<string>& words) { vector<string> res; if (words.empty() || board.empty() || board[0].empty()) return res; vector<vector<bool> > visit(board.size(), vector<bool>(board[0].size(), false)); Trie T; for (auto &a : words) T.insert(a); for (int i = 0; i < board.size(); ++i) { for (int j = 0; j < board[i].size(); ++j) { if (T.root->child[board[i][j] - 'a']) { search(board, T.root->child[board[i][j] - 'a'], i, j, visit, res); } } } return res; } void search(vector<vector<char> > &board, TrieNode *p, int i, int j, vector<vector<bool> > &visit, vector<string> &res) { if (!p->str.empty()) { res.push_back(p->str); p->str.clear(); } int d[][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; visit[i][j] = true; for (auto &a : d) { int nx = a[0] + i, ny = a[1] + j; if (nx >= 0 && nx < board.size() && ny >= 0 && ny < board[0].size() && !visit[nx][ny] && p->child[board[nx][ny] - 'a']) { search(board, p->child[board[nx][ny] - 'a'], nx, ny, visit, res); } } visit[i][j] = false; } };
相似題目:
[LeetCode] 79. Word Search 單詞搜索
[LeetCode] 208. Implement Trie (Prefix Tree) 實現字典樹(前綴樹)