diff --git a/README.md b/README.md index bdd6689..bb6b184 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,7 @@ My LeetCode solutions with Chinese explanation. 我的LeetCode中文题解。 | 208 |[208. Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/)|[C++](solutions/208.%20Implement%20Trie%20(Prefix%20Tree).md)|Medium| | | 209 |[Minimum Size Subarray Sum](https://leetcode.com/problems/minimum-size-subarray-sum/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/209.%20Minimum%20Size%20Subarray%20Sum.md)|Medium| | | 210 |[Course Schedule II](https://leetcode.com/problems/course-schedule-ii/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/210.%20Course%20Schedule%20II.md)|Medium| | +| 212 |[Word Search II](https://leetcode.com/problems/word-search-ii/)|[C++](solutions/212.%20Word%20Search%20II.md)|Hard| | | 213 |[House Robber II](https://leetcode.com/problems/house-robber-ii/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/213.%20House%20Robber%20II.md)|Medium| | | 215 |[Kth Largest Element in an Array](https://leetcode.com/problems/kth-largest-element-in-an-array/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/215.%20Kth%20Largest%20Element%20in%20an%20Array.md)|Medium| | | 216 |[Combination Sum III](https://leetcode.com/problems/combination-sum-iii/)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/216.%20Combination%20Sum%20III.md)|Medium| | diff --git a/solutions/212. Word Search II.md b/solutions/212. Word Search II.md new file mode 100644 index 0000000..9f755c7 --- /dev/null +++ b/solutions/212. Word Search II.md @@ -0,0 +1,89 @@ +# [212. Word Search II](https://leetcode.com/problems/word-search-ii/) + +# 思路 + +这题是[79. Word Search](https://leetcode.com/problems/word-search/)的升级版,79题是判断某个单词是否存在与board中,而此题是给了一堆单词,让返回所有存在的单词。 + +亲测按照79那样直接搜索是会超时的(不然就不是hard题了),那我们只好考虑更加高效的方法。由于是在一个单词集合中查询,那么我们考虑用字典树(Trie),所以我们可以直接把[208题](208.%20Implement%20Trie%20(Prefix%20Tree).md)的字典树实现拿过来用,不过只用到了`insert`操作。 + +字典树建好后,我们就可以DFS了,一旦遇到了字典树某个节点`is_last_letter == true`就说明找到了,将此时对应的单词加入结果数组中;为了避免下一次DFS时重复找到这个单词,我们应该将这里的`is_last_letter`设为false,表示单词集里面没有这个单词了。 + +代码中使用了一个小技巧,类似[79题思路二](79.%20Word%20Search.md)那样,我们使用DFS时不另开visited数组,而是用原数组board来记录某个元素是否被访问过,若被访问过就将board对应位置改成字符`*`,注意DFS结束前要改回来。 + +# C++ +``` C++ +struct TrieNode{ + bool is_last_letter; // 是否是某个单词的结尾 + char letter; + vectornext; // 孩子们 + TrieNode(char cc): is_last_letter(false), letter(cc), + next(vector(26, NULL)){} +}; + +class Trie { +private: + TrieNode *root; +public: + Trie() { + root = new TrieNode('\0'); // 根节点不包含字符 + root -> is_last_letter = true; + } + + TrieNode* getRoot(){return root;} + + /** Inserts a word into the trie. */ + void insert(string word) { + if(word.empty()) return; + TrieNode *p = root; + for(int i = 0; i < word.size(); i++){ + int idx = word[i] - 'a'; + if(NULL == (p -> next)[idx]) // 没找到, 插入即可 + (p -> next)[idx] = new TrieNode(word[i]); + p = (p -> next)[idx]; + } + p -> is_last_letter = true; + } +}; + +class Solution { +private: + int row, col; + vectorres; + const vectordx = {0,0,1,-1}, dy = {1,-1,0,0}; + void DFS(vector>& board, + vector&nodes, int i, int j, string word){ + if(i < 0 || i >= row || j < 0 || j >= col || board[i][j] == '*') return; + + TrieNode *node = nodes[board[i][j] - 'a']; + if(!node) return; + + word.append(1, board[i][j]); + char tmp = board[i][j]; board[i][j] = '*'; + if(node -> is_last_letter) { + res.push_back(word); + // 避免下一次DFS时重复找到这个单词 + node -> is_last_letter = false; + } + for(int k = 0; k < 4; k++) + DFS(board, node -> next, i+dx[k], j+dy[k], word); + + board[i][j] = tmp; + } + +public: + vector findWords(vector>& board, vector& words) { + row = board.size(); + if(!row || words.empty()) return res; + col = board[0].size(); + + Trie tree; + for(string word: words) tree.insert(word); + + for(int i = 0; i < row; i++) + for(int j = 0; j < col; j++) + DFS(board, tree.getRoot() -> next, i, j, ""); + + return res; + } +}; +``` \ No newline at end of file