字典树、前缀树

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;
    }
};
原文地址:https://www.cnblogs.com/Dancing-Fairy/p/12759077.html