Given an integer array nums
, return the maximum result of nums[i] XOR nums[j]
, where 0 ≤ i ≤ j < n
.
Follow up: Could you do this in O(n)
runtime?
Example 1:
Input: nums = [3,10,5,25,2,8] Output: 28 Explanation: The maximum result is 5 XOR 25 = 28.Example 2:
Input: nums = [0] Output: 0Example 3:
Input: nums = [2,4] Output: 6Example 4:
Input: nums = [8,10,2] Output: 10Example 5:
Input: nums = [14,70,53,83,49,91,36,80,92,51,66,70] Output: 127
Constraints:
1 <= nums.length <= 2 * 104
0 <= nums[i] <= 231 - 1
数组中两个数的最大异或值。题意是给一个数组,请输出其中两个数字异或的最大值。
我这里提供一个位运算的做法,大部分内容参考了这个帖子。首先复习一下异或XOR的运算规则:两个二进制的数字,同一个位置上的数字不同,XOR为1;数字相同的时候,XOR为0。所以这里如果要找XOR最大的结果,最好能找到两个数字,他们的二进制表达最好在每一位上都不同。而且XOR是具有交换律的,如果你有a ^ b = c,你同时可以得到a ^ c = b和b ^ c = a。假如a和b是来自于nums的数字的话,我们为了要使c最大,我们可以试图去找一个前缀很大的数字a和一个前缀很小的数字b,这样他们做XOR运算的时候才有可能使c的前缀更大。
这里我们创建一个mask去判断每个二进制数字的前缀。mask是由10000...000到11111...111(32位)。随着mask的变大,比如从10000到11111(我这里暂时用5位表示),如果nums里面的数字跟mask比较的时候,他们的前缀里面也包含1的话,在做AND运算的时候,会得到这些前缀。此时我们在找前缀的同时,把这些前缀存到一个hashset里。每一个mask都会与input数组里面的每一个数字做AND运算,得到一个前缀,set里最终留下的是所有unique的前缀。
此时再创建一个mask叫做temp,也是从1 - 31逐渐增加1的个数。这里我理解temp就是在猜最后XOR的结果,然后往回套,看hashset是否存在两个数字a和b满足a ^ b = temp。判断的方式是对于hashset里面的某个元素a,如果满足a ^ temp = b,同时b也在hashset中,则表明找到了一个有效的temp。
时间O(n)
空间O(n)
Java实现
1 class Solution { 2 // 先确定高位,再确定低位(有点贪心算法的意思),才能保证这道题的最大性质 3 // 一位接着一位去确定这个数位的大小 4 // 利用性质: a ^ b = c ,则 a ^ c = b,且 b ^ c = a 5 public int findMaximumXOR(int[] nums) { 6 int res = 0; 7 int mask = 0; 8 for (int i = 31; i >= 0; i--) { 9 // 注意点1:注意保留前缀的方法,mask 是这样得来的 10 // 用异或也是可以的 mask = mask ^ (1 << i); 11 mask = mask | (1 << i); 12 // System.out.println("mask is " + Integer.toBinaryString(mask)); 13 Set<Integer> set = new HashSet<>(); 14 for (int num : nums) { 15 // 注意点2:这里使用 & ,保留前缀的意思(从高位到低位) 16 set.add(num & mask); 17 } 18 19 // 这里先假定第 n 位为 1 ,前 n-1 位 res 为之前迭代求得 20 int temp = res | (1 << i); 21 System.out.println("temp is " + Integer.toBinaryString(temp)); 22 for (Integer prefix : set) { 23 if (set.contains(prefix ^ temp)) { 24 res = temp; 25 break; 26 } 27 } 28 } 29 return res; 30 } 31 }