zoukankan      html  css  js  c++  java
  • 【LeetCode】前缀树 trie(共14题)

    【208】Implement Trie (Prefix Tree) (2018年11月27日)

    实现基本的 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  */
    View Code

      

    【211】Add and Search Word - Data structure design (2018年11月27日)

    实现这两个接口:(1) void addWord(word); (2) bool search(word)。 search 的时候输入有可能是个正则表达式。'.' 字符代表任何一个字母。输入保证只有小写字母和'. 。

    题解:本题比 208 题更加多了一些条件,如果 search 的时候发现 word[i]是 '.' 的时候, 用 backtracking 递归做。

     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  */
    View Code

      

    【212】Word Search II 

    【336】Palindrome Pairs 

    【421】Maximum XOR of Two Numbers in an Array 

    【425】Word Squares 

    【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  */
    View Code

    【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 };
    View Code

    【745】Prefix and Suffix Search 

  • 相关阅读:
    Spring MVC-表单(Form)标签-单选按钮(RadioButton)示例(转载实践)
    Ubuntu 16.04中VirtualBox 5.1使用U盘/USB设备的方法
    Spring MVC-表单(Form)标签-复选框集合(Checkboxes)示例(转载实践)
    Ubuntu 16.04下减小/释放/清理VirtualBox虚拟硬盘文件的大小
    关注点分离
    谈代码注释
    DelegatingFilterProxy类的作用
    GOPS 2018全球运维大会上海站 参会感悟梳理
    Java switch case
    Android 微信网址分享添加网络图片
  • 原文地址:https://www.cnblogs.com/zhangwanying/p/9964323.html
Copyright © 2011-2022 走看看