这道题我最终还是没能完全做出来,不过无妨,菜鸡的我向来对这种困难题都是抱着随意的心理。主要是学习里面的知识点:字典树
字典树就是相当于每一个节点都是一个同类型的指针数组,输入一段数字(或字符),如果当前字符后有字符,若不存在就继续加入,再指向下一个节点,一直延续直到整个串结束(插入过程),其实比较好理解。
这一题主要就是利用了字典树的特征,按照位来分析,并且是从高位到底位,先判断与当前位相异的节点是否存在,若存在刚刚好指向此节点,不存在的话只能指向同节点。从高位考虑就能够找到最大的异或结果。这过程还有好多细节之类,总是无论无何还是超时了,以下是超时的错误范例(或许能等个有缘人改进?)。
//字典树
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;
}
};
这篇博客探讨了一种使用字典树(Trie)数据结构来解决寻找最大异或值的问题。作者详细解释了字典树的插入过程,并展示了如何在给定数字集合和查询中,通过遍历高位到低位,寻找与查询值异或结果最大的数字。尽管代码在处理某些情况时超时,但作者希望这个例子能引发读者对优化算法的思考。
1439

被折叠的 条评论
为什么被折叠?



