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

这篇博客探讨了一种使用字典树(Trie)数据结构来解决寻找最大异或值的问题。作者详细解释了字典树的插入过程,并展示了如何在给定数字集合和查询中,通过遍历高位到低位,寻找与查询值异或结果最大的数字。尽管代码在处理某些情况时超时,但作者希望这个例子能引发读者对优化算法的思考。

这道题我最终还是没能完全做出来,不过无妨,菜鸡的我向来对这种困难题都是抱着随意的心理。主要是学习里面的知识点:字典树
字典树就是相当于每一个节点都是一个同类型的指针数组,输入一段数字(或字符),如果当前字符后有字符,若不存在就继续加入,再指向下一个节点,一直延续直到整个串结束(插入过程),其实比较好理解。
这一题主要就是利用了字典树的特征,按照位来分析,并且是从高位到底位,先判断与当前位相异的节点是否存在,若存在刚刚好指向此节点,不存在的话只能指向同节点。从高位考虑就能够找到最大的异或结果。这过程还有好多细节之类,总是无论无何还是超时了,以下是超时的错误范例(或许能等个有缘人改进?)。

//字典树
class Trie
{
public:
    vector<Trie*> next;//记录下一个
    Trie():next(2){}//构造函数,利用初始化列表
    void Insert(int val)
    {
        Trie* t=this;
        //从高位到低位插入
        for(int i=29;i>=0;--i)
        {
            int x=(val>>i)&1;
            if(t->next[x]==nullptr)
               t->next[x]=new Trie;
            t=t->next[x];
        }
    }
};
class Solution {
    //寻找与val异或的最大结果
    int FindMax(Trie* root,int val)
    {
        Trie* t=root;
        int num(0);
        for(int i=29;i>=0;--i)
        {
            num=num<<1;//左移一
            int x=(val>>i)&1;
            //尽量找与当前位相反的数值
            if(t->next[x^1]!=nullptr)
            {
                num+=1;
                t=t->next[x^1];
            }
            else//没有与当前值相反的值那就只能相同了
            {
                num+=0;
                t=t->next[x];
            }
        }
        return num;
    }
public:
    vector<int> maximizeXor(vector<int>& nums, vector<vector<int>>& queries) {
        sort(nums.begin(),nums.end());
        //后续会打乱queries的顺序,所以增添一个下标
        for(int i=0;i<queries.size();++i)
           queries[i].push_back(i);
        //按照mi从小到大排序,为了字典树元素的增添
        sort(queries.begin(),queries.end(),[&](const vector<int> a,const vector<int> b){
            return a[1]<b[1];
        });
        vector<int> result(queries.size());//记录结果
        int i=0;//记录nums下标
        Trie* root=new Trie;//构建的字典树
        for(auto& k:queries)
        {
            int mi=k[1];
            //将不大于mk的值插入到字典树
            while(i<nums.size())
            {
                if(nums[i]>mi) break;
                root->Insert(nums[i]);
                ++i;
            }
            //i=0表示root为空,即没有数字比mi小或相等
            if(i==0) result[k[2]]=-1;
            else 
              result[k[2]]=FindMax(root,k[0]);
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值