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.
Example:
Input: board = [ ['o','a','a','n'], ['e','t','a','e'], ['i','h','k','r'], ['i','f','l','v'] ] words =["oath","pea","eat","rain"]Output:["eat","oath"]
Note:
- All inputs are consist of lowercase letters
a-z. - The values of
wordsare distinct.
You would need to optimize your backtracking to pass the larger test. Could you stop backtracking earlier?
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.
這道題是在之前那道 Word Search 的基礎上做了些拓展,之前是給一個單詞讓判斷是否存在,現在是給了一堆單詞,讓返回所有存在的單詞,在這道題最開始更新的幾個小時內,用 brute force 是可以通過 OJ 的,就是在之前那題的基礎上多加一個 for 循環而已,但是后來出題者其實是想考察字典樹的應用,所以加了一個超大的 test case,以至於 brute force 無法通過,強制我們必須要用字典樹來求解。LeetCode 中有關字典樹的題還有 Implement Trie (Prefix Tree) 和 Add and Search Word - Data structure design,那么我們在這題中只要實現字典樹中的 insert 功能就行了,查找單詞和前綴就沒有必要了,然后 DFS 的思路跟之前那道 Word Search 基本相同,請參見代碼如下:
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; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/212
類似題目:
Unique Paths III
參考資料:
https://leetcode.com/problems/word-search-ii/
https://leetcode.com/problems/word-search-ii/discuss/59780/Java-15ms-Easiest-Solution-(100.00)
