【208】Implement Trie (Prefix Tree) (2018年11月27日)node
實現基本的 trie 樹,包括 insert, search, startWith 操做等 api。程序員
題解:《程序員代碼面試指南》chp5, 最後一題。 裏面講了怎麼實現。這個就看代碼吧。沒啥好說的了。面試
1 class Trie { 2 public: 3 /** Initialize your data structure here. */ 4 Trie() { 5 root = new TrieNode(); 6 } 7 8 /** Inserts a word into the trie. */ 9 void insert(string word) { 10 if (word.empty()) {return;} 11 const int n = word.size(); 12 TrieNode* node = root; 13 int index = 0; 14 for (int i = 0; i < n; ++i) { 15 index = word[i] - 'a'; 16 if (node->mp.find(index) == node->mp.end()) { 17 node->mp[index] = new TrieNode(); 18 } 19 node = node->mp[index]; 20 node->path++; 21 } 22 node->end++; 23 } 24 25 /** Returns if the word is in the trie. */ 26 bool search(string word) { 27 if (word.empty()) {return false;} 28 TrieNode* node = root; 29 const int n = word.size(); 30 int index = 0; 31 for (int i = 0; i < n; ++i) { 32 index = word[i] - 'a'; 33 if (node->mp.find(index) == node->mp.end()) { 34 return false; 35 } 36 node = node->mp[index]; 37 if (node->path == 0) { 38 return false; 39 } 40 } 41 return node->end >= 1; 42 } 43 44 /** Returns if there is any word in the trie that starts with the given prefix. */ 45 bool startsWith(string prefix) { 46 if (prefix.empty()) {return false;} 47 const int n = prefix.size(); 48 TrieNode* node = root; 49 int index = 0; 50 for (int i = 0; i < n; ++i) { 51 index = prefix[i] - 'a'; 52 if (node->mp.find(index) == node->mp.end()) { 53 return false; 54 } 55 node = node->mp[index]; 56 if (node->path == 0) { 57 return false; 58 } 59 } 60 return node->path >= 1; 61 } 62 63 //define trie node 64 struct TrieNode{ 65 int path; //表明多少個單詞共用這個結點 66 int end; //表明多少個單詞以這個結點結尾 67 map<int, TrieNode*> mp; 68 TrieNode() { 69 path = 0, end = 0; 70 } 71 }; 72 TrieNode* root; 73 }; 74 75 /** 76 * Your Trie object will be instantiated and called as such: 77 * Trie obj = new Trie(); 78 * obj.insert(word); 79 * bool param_2 = obj.search(word); 80 * bool param_3 = obj.startsWith(prefix); 81 */
【211】Add and Search Word - Data structure design (2018年11月27日)正則表達式
實現這兩個接口:(1) void addWord(word); (2) bool search(word)。 search 的時候輸入有多是個正則表達式。'.' 字符表明任何一個字母。輸入保證只有小寫字母和'. 。api
題解:本題比 208 題更加多了一些條件,若是 search 的時候發現 word[i]是 '.' 的時候, 用 backtracking 遞歸作。app
1 class WordDictionary { 2 public: 3 struct TrieNode { 4 int path; 5 int end; 6 map<int, TrieNode*> mp; 7 TrieNode() { 8 path = 0; 9 end = 0; 10 } 11 }; 12 /** Initialize your data structure here. */ 13 WordDictionary() { 14 root = new TrieNode(); 15 } 16 17 /** Adds a word into the data structure. */ 18 void addWord(string word) { 19 if (word.empty()) {return;} 20 const int n = word.size(); 21 TrieNode* node = root; 22 int index = 0; 23 for (int i = 0; i < n; ++i) { 24 index = word[i] - 'a'; 25 if (node->mp.find(index) == node->mp.end()) { 26 node->mp[index] = new TrieNode(); 27 } 28 node = node->mp[index]; 29 node->path++; 30 } 31 node->end++; 32 } 33 34 /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */ 35 bool search(string word) { 36 if (word.empty()) {return false;} 37 return search(word, 0, root); 38 } 39 bool search(string word, int cur, TrieNode* node) { 40 const int n = word.size(); 41 if (cur == n) { 42 if (node->end >= 1) { 43 return true; 44 } 45 return false; 46 } 47 if (word[cur] == '.') { 48 map<int, TrieNode*> mptemp = node->mp; 49 TrieNode* father = node; 50 for (auto ele : mptemp) { 51 node = ele.second; 52 if (search(word, cur+1, node)) { 53 return true; 54 } 55 node = father; 56 } 57 return false; 58 } else { 59 int index = word[cur] - 'a'; 60 if (node->mp.find(index) == node->mp.end()) { 61 return false; 62 } 63 node = node->mp[index]; 64 if (node->path == 0) { 65 return false; 66 } 67 return search(word, cur+1, node); 68 } 69 return true; 70 } 71 TrieNode* root; 72 }; 73 74 /** 75 * Your WordDictionary object will be instantiated and called as such: 76 * WordDictionary obj = new WordDictionary(); 77 * obj.addWord(word); 78 * bool param_2 = obj.search(word); 79 */
【212】Word Search II ide
【336】Palindrome Pairs spa
【421】Maximum XOR of Two Numbers in an Array code
【425】Word Squares blog
【472】Concatenated Words
【642】Design Search Autocomplete System
【648】Replace Words
【676】Implement Magic Dictionary
【677】Map Sum Pairs (2019年3月26日)
實現兩個method,
Implement a MapSum class with insert
, and sum
methods.
For the method insert
, you'll be given a pair of (string, integer). The string represents the key and the integer represents the value. If the key already existed, then the original key-value pair will be overridden to the new one.
For the method sum
, you'll be given a string representing the prefix, and you need to return the sum of all the pairs' value whose key starts with the prefix.
Example 1:
Input: insert("apple", 3), Output: Null Input: sum("ap"), Output: 3 Input: insert("app", 2), Output: Null Input: sum("ap"), Output: 5
題解:用trie樹,用map記錄當前key是否在trie樹裏面,若是在的話,須要覆蓋當前的值。
1 class TrieNode { 2 public: 3 TrieNode(char _c) : c(_c), pass(0) { 4 children.resize(26, nullptr); 5 } 6 char c; 7 vector<TrieNode*> children; 8 int pass = 0; 9 }; 10 class MapSum { 11 public: 12 /** Initialize your data structure here. */ 13 MapSum() { 14 root = new TrieNode('/'); 15 } 16 ~MapSum() { 17 if (root) delete root; 18 } 19 void insert(string key, int val) { 20 if (cache.count(key)) { 21 int diff = val - cache[key]; 22 cache[key] = val; 23 val = diff; 24 } else { 25 cache[key] = val; 26 } 27 TrieNode* node = root; 28 for (auto& c : key) { 29 if (node->children[c-'a'] == nullptr) { 30 node->children[c-'a'] = new TrieNode(c); 31 } 32 node = node->children[c-'a']; 33 node->pass += val; 34 } 35 } 36 int sum(string prefix) { 37 if (!root) {return 0;} 38 TrieNode* node = root; 39 for (auto& c : prefix) { 40 if (node->children[c-'a'] == nullptr) {return 0;} 41 node = node->children[c-'a']; 42 } 43 return node->pass; 44 } 45 TrieNode* root; 46 unordered_map<string, int> cache; 47 }; 48 49 /** 50 * Your MapSum object will be instantiated and called as such: 51 * MapSum* obj = new MapSum(); 52 * obj->insert(key,val); 53 * int param_2 = obj->sum(prefix); 54 */
【692】Top K Frequent Words
【720】Longest Word in Dictionary (2019年2月14日,谷歌tag)
給了一個 wordlist, 返回一個最長的單詞,這個單詞必須是每次從尾部扔掉一個字母的單詞,依然在wordlist中。
題解:我用了trie樹 + sorting,先用wordlist中全部的單詞insert進 trie 樹,而後排序後從最長的單詞開始,檢查是否符合規則 ,time complexity: O(sigma(Wi) + nlogn)
1 class Trie { 2 public: 3 class TrieNode { 4 public: 5 TrieNode(char ch) :c(ch) { 6 children.resize(26, nullptr); 7 } 8 ~TrieNode() { 9 for (auto node : children) { 10 delete node; 11 } 12 } 13 char c; 14 vector<TrieNode*> children; 15 bool isEnd = false; 16 }; 17 Trie(): root(new TrieNode('/')) {} 18 std::unique_ptr<TrieNode> root; // TrieNode* root; 19 void insert(string& s) { 20 TrieNode* cur = root.get(); 21 for (auto& letter : s) { 22 if (cur->children[letter-'a'] == nullptr) { 23 cur->children[letter-'a'] = new TrieNode(letter); 24 } 25 cur = cur->children[letter - 'a']; 26 } 27 cur->isEnd = true; 28 } 29 bool check(string& s) { 30 TrieNode* cur = root.get(); 31 for (auto& letter : s) { 32 cur = cur->children[letter-'a']; 33 if (!cur->isEnd) {return false;} 34 } 35 return true; 36 } 37 }; 38 class Solution { 39 public: 40 string longestWord(vector<string>& words) { 41 Trie trie; 42 //sort(words.begin(), words.end(), cmp); 43 sort(words.begin(), words.end(), 44 [](const string& s1, const string& s2) { 45 if (s1.size() != s2.size()) { 46 return s1.size () > s2.size(); 47 } 48 return s1 < s2; 49 }); 50 for (auto& w : words) { 51 trie.insert(w); 52 } 53 string res = ""; 54 for (auto& w : words) { 55 if (trie.check(w)) { 56 return w; 57 } 58 } 59 return ""; 60 } 61 static bool cmp(const string& s1, const string& s2) { 62 if (s1.size() == s2.size()) { 63 return s1 < s2; 64 } 65 return s1.size() > s2.size(); 66 } 67 };
【745】Prefix and Suffix Search