Leetcode421. 找出数组中两个元素异或的最大值

来源:互联网 发布:html ccs js 编辑:程序博客网 时间:2024/05/16 06:33

Leetcode421. Maximum XOR of Two Numbers in an Array

题目

Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 2^31.
Find the maximum result of ai XOR aj, where 0 ≤ i, j < n.
Could you do this in O(n) runtime?

Example:
Input: [3, 10, 5, 25, 2, 8]
Output: 28
Explanation: The maximum result is 5 ^ 25 = 28.

解题分析

题目的要求很简单,就是让我们找出数组中两个元素异或的最大值,并且要求我们实现的算法的时间复杂度为O(n)。按照常理,我们会对数组中所有元素对进行异或然后进行比较,这样的话时间复杂度就为O(n^2),很显然不符合题目的要求,那么我们就只能另辟蹊径了。
我们可以这样想,异或的基本原理就是将两个数字分别转成32位二进制后,进行逐位比较,如果同个位置上的数字不同,则该位为1,否则为0。根据这个原理,我们从左高位进行计算,用一个掩码mask来作为底,其中mask当前位i到左高位的所有位置上的数字为1,其它位置为0,即11…10…0。将数组中的每个元素分别与mask进行与运算,将与运算的结果存进集合set中。
假设至少存在两个数在当前位i上的数字不同,则可有假设:当前异或的最大值temp为max|2^i,那么怎样验证当前位i上至少存在两个数不同呢?我们可以借助前面求得的temp值,将集合中的每个元素与temp进行异或,如果在集合中能找到一个数等于另一个数与temp异或的结果,那就说明假设成立,将temp赋值给异或最大值max。
为什么呢这样假设就成立了呢?我们可以这样看,我们知道,在当前位i,mask上的数字为1,其低位全部为0。由于集合set存放的元素是数组元素与mask进行与运算的结果,因此如果当前位i上至少有两个数不同,那么进行与运算后的结果当前位i就必然有0和1两种情况,而低位的数字都相同、均为0。而我们知道,1^1=0,0^1=1,由于低位都相同,所以根据异或的结果就可以知道在当前位i上是否有两个数字满足要求了。
这样当32位数字遍历完后,最后得到的max值就是最后的答案。

源代码

class Solution {public:    int findMaximumXOR(vector<int>& nums) {        int max = 0, mask = 0;        for (int i = 31; i >= 0; i--) {            set<int> set;            mask = mask | (1 << i);            for (int num : nums) {                set.insert(num & mask);            }            int temp = max | (1 << i);            for (int element : set) {                if (set.find(element ^ temp) != set.end()) {                    max = temp;                    break;                }            }        }        return max;    }};

以上是我对这道问题的一些想法,有问题还请在评论区讨论留言~