[H字典树] lc1707. 与数组中元素的最大异或值(trie+知识理解+离线处理)

1. 题目来源

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

相关题目:

2. 题目解析

没啥难度,整体思想和 [Trie] lc421. 数组中两个数的最大异或值(Trie+Trie的不同写法+算法对比) 一样,加了离线处理罢了。

trie 的经典应用,用来解决最大异或值问题。这里需要根据查询顺序返回答案,很明显的离线处理,但是我一开始使用 pair<vector<int>, int> 维护查询数组和下标时,TLE 了,进而修改为静态结构体解决了。1e5 的数据也能 TLE,是真的服…

整体思路都一样,没啥好讲的,模板题。


时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
空间复杂度: O ( n ∗ 32 ) O(n*32) O(n32)

代码:

const int N = 1e5+5;
int s[N * 32][2], idx;

struct Node {
    int x, m, idx;
    bool operator<(const Node M) const {
        return m < M.m;
    }
} Q[N];

class Solution {
public:
    void insert(int x) {
        int p = 0;
        for (int i = 31; ~i; i -- ) {
            int u = x >> i & 1;
            if (!s[p][u]) s[p][u] = ++ idx;
            p = s[p][u];
        }
    }

    int query(int x) {
        int res = 0, p = 0;
        for (int i= 31; ~i; i -- ) {
            int u = x >> i & 1;
            if (s[p][!u]) res = res * 2 + !u, p = s[p][!u];
            else res = res * 2 + u, p = s[p][u];
        }
        return res ^ x;
    }
		
	// 注意:更加直观,这里的 res=res*2+1等价于 res=res*2+!u
	// 因为 u^!u=1,故最终的答案不需要再与 x 异或了,相当于每一位都已经异或了
	// res=res*2+!u 是搞出来了 trie 中与 x 最相反的数是多少,
	// 其存在于 trie 中, 在 trie 中具备实际意义!
	// 而 res=res*2+1 是直接搞出来 trie 中与 x 相反数的异或值,其不一定存在于 trie 中
	// 在 trie 中不具备实际意义!
	// 理解要透彻
	int query(int x) {
        int res = 0, p = 0;
        for (int i= 31; ~i; i -- ) {
            int u = x >> i & 1;
            if (s[p][!u]) res = res * 2 + 1, p = s[p][!u];
            else res = res * 2, p = s[p][u];
        }
        return res;
    }
    
    vector<int> maximizeXor(vector<int>& nums, vector<vector<int>>& queries) {
        memset(s, 0, sizeof s), idx = 0;

        int n = queries.size();
        for (int i = 0; i < n; i ++ ) Q[i] = {queries[i][0], queries[i][1], i};
        sort(nums.begin(), nums.end());
        sort(Q, Q + n);

        vector<int> res(n);
        for (int i = 0, j = 0; i < n; i ++ ) {
            int x = Q[i].x, m = Q[i].m, idx = Q[i].idx;

            while (j < nums.size() && nums[j] <= m) insert(nums[j ++ ]);
            if (!j) res[idx] = -1;
            else res[idx] = query(x);
        }
        return res;
    }
};

TLE 代码:

const int N = 1e5+5;
int s[N * 32][2], idx;

class Solution {
public:
    void insert(int x) {
        int p = 0;
        for (int i = 31; ~i; i -- ) {
            int u = x >> i & 1;
            if (!s[p][u]) s[p][u] = ++ idx;
            p = s[p][u];
        }
    }

    int query(int x) {
        int res = 0, p = 0;
        for (int i= 31; ~i; i -- ) {
            int u = x >> i & 1;
            if (s[p][!u]) res = res * 2 + !u, p = s[p][!u];
            else res = res * 2 + u, p = s[p][u];
        }
        return res ^ x;
    }
    
    vector<int> maximizeXor(vector<int>& nums, vector<vector<int>>& queries) {
        memset(s, 0, sizeof s), idx = 0;

        int n = queries.size();
        vector<pair<vector<int>, int>> Q;
        int cnt = 0;
        for (auto e : queries) Q.push_back({e, cnt ++ });

        sort(nums.begin(), nums.end());
        sort(Q.begin(), Q.end(), [](pair<vector<int>, int> a, pair<vector<int>, int> b) {
            return a.first[1] < b.first[1];
        });

        vector<int> res(n);
        for (int i = 0, j = 0; i < n; i ++ ) {
            int x = Q[i].first[0], m = Q[i].first[1], idx = Q[i].second;

            while (j < nums.size() && nums[j] <= m) insert(nums[j ++ ]);
            if (!j) res[idx] = -1;
            else res[idx] = query(x);
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值