diff --git a/lectures/27_hybrid_data_structures/README.md b/lectures/27_hybrid_data_structures/README.md index f42dc10..59d8b86 100644 --- a/lectures/27_hybrid_data_structures/README.md +++ b/lectures/27_hybrid_data_structures/README.md @@ -94,7 +94,7 @@ for the key (or NULL or a special value, e.g., ’-1’, if the path to that poi ![alt text](trie.png "trie") -- Lookup in the structure is fast, O(m) where m is the length (# of characters) in the string. A hash table has similar lookup (since we have to hash the string which generally involves looking at every letter). If m << n, we can say this is O(1). +- Lookup in the structure is fast, O(m) where m is the length (# of characters) in the string. ## 27.7 Trie / Prefix Tree - Discussion @@ -105,3 +105,4 @@ for the key (or NULL or a special value, e.g., ’-1’, if the path to that poi - [Leetcode problem 208: Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/). Solution: [p208_trie.cpp](../../leetcode/p208_trie.cpp). - [Leetcode problem 14: Longest Common Prefix](https://leetcode.com/problems/longest-common-prefix/). Solution: [p14_longest_common_prefix.cpp](../../leetcode/p14_longest_common_prefix.cpp). +- [Leetcode problem 212: Word Search II](https://leetcode.com/problems/word-search-ii/). Solution: [p212_word_search_ii.cpp](../../leetcode/p212_word_search_ii.cpp). diff --git a/leetcode/p212_word_search_ii.cpp b/leetcode/p212_word_search_ii.cpp new file mode 100644 index 0000000..2eee0b1 --- /dev/null +++ b/leetcode/p212_word_search_ii.cpp @@ -0,0 +1,105 @@ +class TrieNode { +public: + TrieNode(){ + is_word_complete = false; + for(int i=0;i<26;i++){ + // initialize all 26 pointers to NULL + // we can't do children[i] = NULL; here, because subscripting doesn't make sense until we add elements into the vector. + children.push_back(nullptr); + } + } + // so that we can use TrieNode's private members in Trie. + friend class Trie; +//private: + // also store the word itself + string word; + bool is_word_complete; + // each node has 26 children, storing letters from 'a' to 'z' + vector children; +}; + +class Trie { +public: + Trie() { + // root is just a pointer + root = new TrieNode; + } + void insert(string word) { + char c; + int size = word.length(); + TrieNode* node = root; + for(int i=0;ichildren[c-'a']==NULL){ + node->children[c-'a'] = new TrieNode; + } + node = node->children[c-'a']; + } + // store the word at this node + node->word = word; + node->is_word_complete = true; + } + +// private: + // we do not store characters in root. + TrieNode* root; +}; + +class Solution { +public: + void search(vector>& board, int i, int j, TrieNode* node, vector& ans){ + // if out of bounds + if(i<0 || i>=board.size() || j<0 || j>=board[0].size()){ + return; + } + + if(board[i][j]=='0'){ + return; + } + + char c; + // save board[i][j] in c. + c = board[i][j]; + node = node->children[c-'a']; + // if we reach this point, it means this is a wrong path. + if(node==NULL){ + return; + } + if(node->is_word_complete){ + ans.push_back(node->word); + // we have used this word, now we have to "remove" it from the trie. + node->is_word_complete = false; + } + + // so board[i][j] won't be reused by this current path. + board[i][j] = '0'; + // this isn't a true or false search, so no matter what, we have to search all 4 directions + search(board, i-1, j, node, ans); + search(board, i+1, j, node, ans); + search(board, i, j-1, node, ans); + search(board, i, j+1, node, ans); + // restore board[i][j] + board[i][j] = c; + return; + } + + vector findWords(vector>& board, vector& words) { + vector ans; + Trie trie; + int index = 0; + bool found = false; + int size = words.size(); + // build the trie + for(int i=0;i