LeetCode421:数组中两个数的最大异或值

目录

一、题目描述

二、解题思路

三、代码实现


一、题目描述

给定一个非空数组,数组中元素为 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.

二、解题思路

这题O(n^2)的想法很容易,但是超时也是绝对的。超时的原因在于,我们需要把每个数依次跟其余所有数进行异或操作才能得到最大值。

如果有一种方法,能让我们每个数可以同时跟剩余所有的数同时进行异或操作,那时间复杂度不就是一次遍历就可以了吗?

顺着这个想法可以想到字典树,字典树又叫前缀树。先把每个数字按照二进制位构建字典树(此时字典树是一棵二叉树),建树示意图如下,以下图片均来自力扣官方题解;

LeetCode421:数组中两个数的最大异或值_第1张图片

然后把数组中的每个数同样按照二进制位依次去匹配,匹配的过程如下:

因为结果是求最大的异或值,所以:

  • 如果该数的当前位是1,若存在0,则选择0异或;
  • 如果该数的当前位是0,若存在1,则选择1异或。

LeetCode421:数组中两个数的最大异或值_第2张图片

另:题解中有大佬利用异或的性质(a^b=c, a^c=b, b^c=a)做了另一种解法,同样很巧妙,值得学习。这里贴出链接。

https://leetcode-cn.com/problems/maximum-xor-of-two-numbers-in-an-array/solution/li-yong-yi-huo-yun-suan-de-xing-zhi-tan-xin-suan-f/

三、代码实现

#include 
using namespace std;

class node {
   public:
    //只有0和1两个分支
    node* TrieNode[2];

    node() { memset(TrieNode, 0, sizeof(TrieNode)); }
    ~node() {
        for (int i = 0; i < 2; i++) {
            delete TrieNode[i];
        }
    }
};

class Solution {
   public:
    node* Root;

    Solution() { Root = new node(); }
    ~Solution() { delete Root; }

    int findMaximumXOR(vector& nums) {
        int n = nums.size();
        int res = 0;
        //构建字典树
        //把每个数字按照位插入进字典树
        for (int i = 0; i < n; i++) {
            node* p = Root;
            for (int j = 31; j >= 0; j--) {
                int bit = nums[i] >> j & 1;
                if (!p->TrieNode[bit]) {
                    p->TrieNode[bit] = new node();
                }
                p = p->TrieNode[bit];
            }
        }

        //分别拿每个数去跟字典树贪心的进行异或操作
        for (int i = 0; i < n; i++)
        {
            node* p = Root;
            int tmp = 0;
            for (int j = 31; j >= 0; j--) {
                int bit = nums[i] >> j & 1;
                //如果该数的当前位是1,那么为了异或的结果最大,必须去寻找0来跟他异或
                //如果该数的当前位是0,那么为了异或的结果最大,必须去寻找1来跟他异或
                if (bit == 1) {
                    tmp += p->TrieNode[0] ? 1 << j : 0 ;
                    p = p->TrieNode[0] ? p->TrieNode[0] : p->TrieNode[1] ;
                }else{
                    tmp += p->TrieNode[1] ? 1 << j : 0 ;
                    p = p->TrieNode[1] ? p->TrieNode[1] : p->TrieNode[0] ;
                }
            }
            res = max(res, tmp);
        } 
        return res;
    }
};

int main() {
    vector nums = {3, 10, 5, 25, 2, 8};
    Solution *s = new Solution();
    cout << s->findMaximumXOR(nums);
    return 0;
}

 

你可能感兴趣的:(刷题笔记)