• 字典树、前缀树


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

    给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 2^31 。

    找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i,  j < n 。

    你能在O(n)的时间解决这个问题吗?

    class Solution {
    public:
        int Max_xor=-1;
        string numToBinaryString(int n){
            string res="";
            for(int i=0;i<31;i++){
                if(( n & 1 )== 0)res="0"+res;
                else res="1"+res;
                n = n >> 1;
            }
            return res;
        }
        void MXOR(TreeNode* p, TreeNode* q,int k){
            if(p->val+q->val==1)k = k << 1 | 1;
            else k = k << 1;
            int c1=(p->left!=NULL)+(p->right!=NULL),c2=(q->left!=NULL)+(q->right!=NULL);
            if(c1==0&&c2==0){
                Max_xor=max(Max_xor,k);
                return;
            }
            if(c1==2&&c2==2){
                MXOR(p->left,q->right,k);
                MXOR(p->right,q->left,k);
            }
            else if(c1==2&&c2==1){
                if(q->left)
                    MXOR(p->right,q->left,k);
                else
                    MXOR(p->left,q->right,k);
            }
            else if(c1==1&&c2==2){
                if(p->left)
                    MXOR(p->left,q->right,k);
                else
                    MXOR(p->right,q->left,k);
            }
            else{
                TreeNode* a=p->left==NULL?p->right:p->left;
                TreeNode* b=q->left==NULL?q->right:q->left;
                MXOR(a,b,k);
            }
        }
        int findMaximumXOR(vector<int>& nums) {
            TreeNode* root=new TreeNode(0);
            TreeNode* p;
            
            for(int i=0;i<nums.size();i++){
                string res=numToBinaryString(nums[i]);
                p=root;
                int k=0;
                for(int j=0;j<res.length();j++){
                    if(res[j]=='0'){
                        if(p->left==NULL){
                            TreeNode* tmp=new TreeNode(0);
                            p->left=tmp;
                        }
                        p=p->left;
                    }
                    else{
                        if(p->right==NULL){
                            TreeNode* tmp=new TreeNode(1);
                            p->right=tmp;
                        }
                        p=p->right;
                    }
                }
            }
            int k=0;
            while((!root->left||!root->right)&&(root->left||root->right)){
                if(!root->left){
                    root=root->right;
                }
                else{
                    root=root->left;
                }
            }
            if(root->left==NULL&&root->right==NULL)return 0;
            MXOR(root->left, root->right,0);
            return Max_xor;
        }
    };

     图片来源及官网题解:https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/solution/shu-zu-zhong-liang-ge-shu-de-zui-da-yi-huo-zhi-by-/

    面试题 17.17. 多次搜索

    给定一个较长字符串big和一个包含较短字符串的数组smalls,设计一个方法,根据smalls中的每一个较短字符串,对big进行搜索。输出smalls中的字符串在big里出现的所有位置positions,其中positions[i]为smalls[i]出现的所有位置。

    输入:
    big = "mississippi"
    smalls = ["is","ppi","hi","sis","i","ssippi"]
    输出: [[1,4],[8],[],[3],[1,4,7,10],[5]]

    根据smalls来创建字典树,对big中逐位进行字典树搜索,字典树的节点上加上end标志标记单词结束

    class Solution {
    public:
        struct Trie{
            char val;
            bool end;
            Trie* next[26]={NULL};
            Trie(char c,bool flag):val(c),end(flag){}
        };
        void creatTrie(string& s,Trie* root){   //将字符串插入到字典树中
            Trie* tmp=root;
            for(int i=0;i<s.length();i++){
                if(tmp->next[s[i]-'a']==NULL){
                    Trie* newNode;
                    if(i==s.length()-1)
                        newNode=new Trie(s[i],true);
                    else
                        newNode=new Trie(s[i],false);
                    tmp->next[s[i]-'a']=newNode;
                } 
                tmp=tmp->next[s[i]-'a'];
            }
            tmp->end=true; //字符串结尾结点设置结束标志为true
        }                       
        vector<vector<int>> multiSearch(string big, vector<string>& smalls) {
            unordered_map<string, int> mp;
            for(int i=0;i<smalls.size();i++){
                mp[smalls[i]]=i;
            }                                       //map保存字符串在smalls中的下标
    
            Trie* root=new Trie('*',false);
            for(string& s:smalls){
                creatTrie(s,root);
            }                                        //构建字典树
    
            vector<vector<int>> ans(smalls.size(),vector<int>());
            for(int i=0;i<big.length();i++){
                Trie* tmp=root;
                string stmp="";    //字典路径上的字符串
                int tag=i;
                while(tag<big.length()&&tmp->next[big[tag]-'a']!=NULL){
                    stmp+=big[tag];
                    tmp=tmp->next[big[tag]-'a'];
                    if(tmp->end==true)ans[mp[stmp]].push_back(i); //找到结束标记,说明stmp是smalls中的一个字符串
                    tag++;
                }
            }
            return ans;
        }
    };
  • 相关阅读:
    【codevs1515】 跳
    【bzoj1227】 SDOI2009—虔诚的墓主人
    【bzoj3505】 Cqoi2014—数三角形
    【bzoj1059】 ZJOI2007—矩阵游戏
    【poj2122】 Optimal Milking
    【poj2455】 Secret Milking Machine
    【poj3084】 Panic Room
    【poj2699】 The Maximum Number of Strong Kings
    【bzoj3218】 a + b Problem
    【bzoj3122】 Sdoi2013—随机数生成器
  • 原文地址:https://www.cnblogs.com/Dancing-Fairy/p/12759077.html
Copyright © 2020-2023  润新知