您的位置:首页 > 其它

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

2017-11-10 16:21 344 查看

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;
}
};


以上是我对这道问题的一些想法,有问题还请在评论区讨论留言~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐