diff --git a/lectures/27_hybrid_data_structures/README.md b/lectures/27_hybrid_data_structures/README.md index 5637125..f42dc10 100644 --- a/lectures/27_hybrid_data_structures/README.md +++ b/lectures/27_hybrid_data_structures/README.md @@ -100,9 +100,8 @@ for the key (or NULL or a special value, e.g., ’-1’, if the path to that poi - What is the worst case # of children for a single node? What are the member variables for the Node class? - Unlike a hash table, we can iterate over the keys in a trie / prefix tree in sorted order. -Exercise: Implement the trie sorted-order iterator (in code or pseudocode) and print the table on the right. ## 27.8 Leetcode Exercises - [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). diff --git a/leetcode/p14_longest_common_prefix.cpp b/leetcode/p14_longest_common_prefix.cpp new file mode 100644 index 0000000..0b72599 --- /dev/null +++ b/leetcode/p14_longest_common_prefix.cpp @@ -0,0 +1,91 @@ +class TrieNode { +public: + // initializing one node + TrieNode(){ + count = 0; + // each node can have at most 26 children: a to z. + // and when accessing child, always remember do that -'a' + for(int i=0;i<26;i++){ + children.push_back(nullptr); + } + } + // so that we can access private member variables. + friend class Trie; +// private: + // count how many words use this node + int count; + std::vector children; +}; + +class Trie { +public: + // initializing the prefix tree + Trie() { + // which basically is initializing the root + // and we guarantee that the root always exists + root = new TrieNode; + } + + void insert(string word) { + int len = word.length(); + TrieNode* current = root; + for(int i=0; ichildren[word[i]-'a'] == nullptr){ + // create a node + current->children[word[i]-'a'] = new TrieNode; + current->children[word[i]-'a']->count++; + // after the insertion, update current + current = current->children[word[i]-'a']; + }else{ + // else, it means this node is already there, just update current + // we make the code duplicated here, but this way it's easier to understand. + current->children[word[i]-'a']->count++; + current = current->children[word[i]-'a']; + } + } + } + +// private: + // just like every tree, we should have a root. + TrieNode* root; +}; + +/** + * Your Trie object will be instantiated and called as such: + * Trie* obj = new Trie(); + * obj->insert(word); + * bool param_2 = obj->search(word); + * bool param_3 = obj->startsWith(prefix); + */ + +class Solution { +public: + string longestCommonPrefix(vector& strs) { + int size = strs.size(); + std::string result; + Trie trie; + TrieNode* current = trie.root; + // step 1, insert every word in trie + for(int i=0;ichildren[strs[0][i]-'a']!=nullptr)){ + // std::cout << current->children[strs[0][i]-'a']->count << ":" << size << std::endl; + } + if(current && (current->children[strs[0][i]-'a']!=nullptr) && current->children[strs[0][i]-'a']->count == size){ + result.push_back(strs[0][i]); + // once it's pushed back, update current so as to move on to the next level. + current = current->children[strs[0][i]-'a']; + }else{ + break; + } + } + return result; + } +};