• 五月集训(第二十三日)字典树


    一、211. 添加与搜索单词 - 数据结构设计

    1.原题链接

    211. 添加与搜索单词 - 数据结构设计

    2.题目描述

            请你设计一个数据结构,支持 添加新单词 和 查找字符串是否与任何先前添加的字符串匹配 。实现词典类 WordDictionary :WordDictionary() 初始化词典对象;void addWord(word) 将 word 添加到数据结构中,之后可以对它进行匹配;bool search(word) 如果数据结构中存在字符串与 word 匹配,则返回 true ;否则,返回 false 。word 中可能包含一些 ‘.’ ,每个 . 都可以表示任何一个字母。

    3.解题思路

            字典树的插入

    4.源码

    class TrieNode{
    public:
        vector<TrieNode*> child;
        bool isWord;
        TrieNode() : child(26, nullptr), isWord(false) {};
        ~TrieNode() {
            for (auto c : child) delete c;
        }
    };
    class WordDictionary {
    public:
        WordDictionary() {
            root = new TrieNode();
        }
        ~WordDictionary() {
            delete root;
        }
        void addWord(string word) {
            TrieNode* p = root;
            for (char c : word) {
                int i = c - 'a';
                if (!p->child[i])
                    p->child[i] = new TrieNode();
                p = p->child[i];
            }
            p->isWord = true;
        }
        
        bool search(string word) {
            return match(word, root, 0);
        }
        
        bool match(string& word, TrieNode* p, int start) {
            if (!p) return false;
            if (start == word.size()) return p->isWord;
            char c = word[start];
            if (c != '.') {
                return match(word, p->child[c - 'a'], start + 1);
            } else {
                for (const auto& child : p->child) {
                    if (match(word, child, start + 1))
                        return true;
                }
            }
            return false;
        }
    private:
        TrieNode* root;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    二、1268. 搜索推荐系统

    1.原题链接

    1268. 搜索推荐系统

    2.题目描述

            给你一个产品数组 products 和一个字符串 searchWord ,products 数组中每个产品都是一个字符串。请你设计一个推荐系统,在依次输入单词 searchWord 的每一个字母后,推荐 products 数组中前缀与 searchWord 相同的最多三个产品。如果前缀相同的可推荐产品超过三个,请按字典序返回最小的三个。请你以二维列表的形式,返回在输入 searchWord 每个字母后相应的推荐产品的列表。

    3.解题思路

            字典树

    4.源码

    struct PreTree{
        PreTree():tree(26),word_flag(0){
        }
        
        void add(string s){
            PreTree * node=this;
            for(int i=0;i<s.size();i++){
                if(node->tree[s[i]-'a']==nullptr){
                    PreTree* new_node=new PreTree();
                    node->tree[s[i]-'a']=new_node;
                }
                node = node->tree[s[i]-'a'];
            }
            node->word_flag=1;
        }
        
        void backtrace(PreTree*node){
            if(node==nullptr){
                return;
            }
            if(ans.size()==3){
                return;
            }
            if(node->word_flag==1){
                ans.push_back(tmp);
            }
            
            for(int i=0;i<26;i++){
                if(node->tree[i]){
                    tmp+=(i+'a');
                    backtrace(node->tree[i]);
                    tmp.pop_back();
                }
            }
        }
    
        vector<string> search(string s){
            ans.clear();
            tmp.clear();
            PreTree * node=this;
            int i;
            for(i=0;i<s.size();i++){
                if(node->tree[s[i]-'a']==nullptr){
                   return ans;
                }
                tmp+=(s[i]);
                node = node->tree[s[i]-'a'];
            }
            backtrace(node);
            return ans;
        }
    
        vector<PreTree*> tree;
        int word_flag;
        vector<string> ans;
        string tmp;
    };
    
    class Solution {
    public:
        vector<vector<string>> suggestedProducts(vector<string>& products, string searchWord) {
            PreTree pt;
            for(auto s:products){
                pt.add(s);
            }
            vector<vector<string>> ans;
            for(int i=1;i<=searchWord.size();i++){
                vector<string> tmp=pt.search(searchWord.substr(0,i));
                ans.push_back(tmp);
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    三、421. 数组中两个数的最大异或值

    1.原题链接

    421. 数组中两个数的最大异或值

    2.题目描述

            给你一个整数数组 nums ,返回 nums[i] XOR nums[j] 的最大运算结果,其中 0 ≤ i ≤ j < n 。进阶:你可以在 O(n) 的时间解决这个问题吗?

    3.解题思路

            

    4.源码

    class Trie
    {
    private:
        Trie* next[2]={nullptr};
    public:
        Trie(){}
    
        void insert(int x)  
        {
            Trie *root=this;
            for(int i=30;i>=0;i--)
            {
                int u=x>>i&1;
                if(!root->next[u])root->next[u]=new Trie();
                root=root->next[u];
            }
        }
    
        int srearch(int x)  
        {
            Trie *root=this;
            int res=0;
            for(int i=30;i>=0;i--)
            {
                int u=x>>i&1;
                if(root->next[!u])root=root->next[!u],res=res*2+!u;
                else root=root->next[u],res=res*2+u;
            }
            res^=x;
            return res;
        }
    };
    
    class Solution {
    public:
        int findMaximumXOR(vector<int>& nums) {
            Trie *root=new Trie();
            for(auto x:nums)root->insert(x);
            int res=0;
            for(auto x:nums)
                res=max(res,root->srearch(x));
            return res;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    四、1707. 与数组中元素的最大异或值

    1.原题链接

    1707. 与数组中元素的最大异或值

    2.题目描述

            给你一个由非负整数组成的数组 nums 。另有一个查询数组 queries ,其中 queries[i] = [xi, mi] 。第 i 个查询的答案是 xi 和任何 nums 数组中不超过 mi 的元素按位异或(XOR)得到的最大值。换句话说,答案是 max(nums[j] XOR xi) ,其中所有 j 均满足 nums[j] <= mi 。如果 nums 中的所有元素都大于 mi,最终答案就是 -1 。返回一个整数数组 answer 作为查询的答案,其中 answer.length == queries.length 且 answer[i] 是第 i 个查询的答案。

    3.解题思路

            字典树插入

    4.源码

    class Trie {
    public:
        const int L = 30;
    
        Trie* children[2] = {};
    
        void insert(int val) {
            Trie* node = this;
            for (int i = L - 1; i >= 0; --i) {
                int bit = (val >> i) & 1;
                if (node->children[bit] == nullptr) {
                    node->children[bit] = new Trie();
                }
                node = node->children[bit];
            }
        }
    
        int getMaxXor(int val) {
            int ans = 0;
            Trie* node = this;
            for (int i = L - 1; i >= 0; --i) {
                int bit = (val >> i) & 1;
                if (node->children[bit ^ 1] != nullptr) {
                    ans |= 1 << i;
                    bit ^= 1;
                }
                node = node->children[bit];
            }
            return ans;
        }
    };
    
    class Solution {
    public:
        vector<int> maximizeXor(vector<int> &nums, vector<vector<int>> &queries) {
            sort(nums.begin(), nums.end());
            int numQ = queries.size();
            for (int i = 0; i < numQ; ++i) {
                queries[i].push_back(i);
            }
            sort(queries.begin(), queries.end(), [](auto &x, auto &y) { return x[1] < y[1]; });
    
            vector<int> ans(numQ);
            Trie* t = new Trie();
            int idx = 0, n = nums.size();
            for (auto &q : queries) {
                int x = q[0], m = q[1], qid = q[2];
                while (idx < n && nums[idx] <= m) {
                    t->insert(nums[idx]);
                    ++idx;
                }
                if (idx == 0) {
                    ans[qid] = -1;
                } else {
                    ans[qid] = t->getMaxXor(x);
                }
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    总结

            第二十三天,一天比一天难。

  • 相关阅读:
    接口测试Http协议下的Get和Post请求的区别
    【STM32】OLED
    java 线程池执行流程源码讲解
    FPGA之旅设计第五例-----IIC通信
    说一下v-model的理解双向绑定 vue响应式原理
    【MySQL】5.触发器
    2022.09.19 学习笔记
    CVPR2022 | 可精简域适应
    【嵌入式环境下linux内核及驱动学习笔记-(13-中断管理)】
    搭建Docker私有镜像仓库
  • 原文地址:https://blog.csdn.net/nannian123/article/details/124936464