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

给定一个非空整数数组,找到最大异或值的两个数。暴力法是计算所有两两异或,但可以优化。注意到高位异或结果更重要,且异或运算的交换律。利用哈希表和树结构能降低计算复杂度到O(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题目描述

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

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

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

示例:

输入: [3, 10, 5, 25, 2, 8]

输出: 28

解释: 最大的结果是 5 ^ 25 = 28.

解题

    暴力法就是计算所有两两异或的结果,求最大值。那如何减少运算量呢?首先我们知道的是高位的异或结果比低位更重要,因此我们应该从最高位开始比较异或结果。其次异或运算有个特点:
                                    c = a ^ b ⇔ b = c ^ a ⇔ a = c ^ b
因此,对于前N位,我们可以知道能得到的最大异或结果,如果数组中存在两个数的前N位异或结果等于这个当前最大结果等价于数组中存在一个等于当前数字前N位与当前最大的异或结果的数字,这样两两计算转化为m次的计算和查找,m为数组的大小。查找的过程我们可以借助哈希表:

class Solution {
public:
    int findMaximumXOR(vector<int>& nums) {
        int max_num = nums[0];
        for (auto i : nums){
            max_num = max_num < i ? i : max_num;
        }
        int bitnum=0;
        while(max_num){
            ++bitnum;
            max_num >>= 1;
        }
        unordered_set<int> temp_nums;
        int cur_max, maxXOR=0, temp_val;
        while (bitnum--){
            maxXOR <<= 1;
            cur_max = maxXOR | 1;
            temp_nums.clear();
            for (auto i : nums) {
                i >>= bitnum;
                if (temp_nums.find(i ^ cur_max)!= temp_nums.end()){
                    maxXOR = cur_max;
                    break;
                }
                temp_nums.emplace(i);
            }
            cur_max << 1;
        }
        return maxXOR;
    }
};

    上述方法中依然存在计算冗余,比如在计算前N位异或结果时,可能某些数字的前N位无法得到当前最大的异或结果,但是在计算N+1位时还是参与了计算,借助树结构就可以避免这些多余的计算过程。

class Solution {
public:
    int findMaximumXOR(vector<int>& nums) {
        int max_num = nums[0], bit_num=0; 
        for(auto i:nums){
            max_num = max_num < i ? i : max_num;
        }
        while (max_num){
            ++bit_num;
            max_num >>= 1;
        }
        root = new Node;
        int maxXOR=0, cur_XOR;
        for (auto i:nums){
            cur_XOR = cal_maxXOR(i, bit_num);
            maxXOR = maxXOR < cur_XOR ? cur_XOR : maxXOR;
        }
        return maxXOR;
    }

private:
    struct Node{
        Node *childs[2] = {NULL};
    }*root;
    int cal_maxXOR(int i, int bit_num){
        Node *cur_node1 = root;
        Node *cur_node2 = root;
        int maxXOR=0;
        while (bit_num--){
            maxXOR <<= 1;
            int index = (i>>bit_num)&1;
            if (cur_node1->childs[index] == NULL)
                cur_node1->childs[index] = new Node;
            cur_node1 = cur_node1->childs[index];
            if (cur_node2->childs[1-index]){
                cur_node2 = cur_node2->childs[1-index];
                maxXOR += 1;
            }
            else{
                cur_node2 = cur_node2->childs[index];
            }
        }
        return maxXOR;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值