力扣笔记–数组中两个数的最大异或值
题目描述
给你一个整数数组 nums ,返回 nums[i] XOR nums[j] 的最大运算结果,其中 0 ≤ i ≤ j < n 。
示例
输入:nums = [3,10,5,25,2,8]
输出:28
解释:最大运算结果是 5 XOR 25 = 28.
第一次解法,暴力,刚好能通过,但是跟没做一样。
class Solution {
public int findMaximumXOR(int[] nums) {
int max = 0;
for(int i = 0; i < nums.length; i++){
for(int j = i + 1; j < nums.length; j++){
if((nums[i] ^ nums[j]) > max){
max = nums[i] ^ nums[j];
}
}
}
return max;
}
}
第二次,看了其他解法,了解到了前缀树,第一解法时间复杂度相当于O(n²),使用前缀树后将第二层循环降为固定常数c。
class Solution {
public class Tree{
Tree left;
Tree right;
}
public int findMaximumXOR(int[] nums) {
int maxNum = 0;
for (int num : nums){
if (num > maxNum)
maxNum = num;
}
int length = 0;
// 得到数组所有元素中最大值,从而得到最大值有多少位,以此构建减少空间使用
while (maxNum != 0){
length++;
maxNum = maxNum>>1;
}
// 构建前缀树
Tree preTree = getPreTree(nums, length);
// 搜索前缀树
int max = searchMax(nums, preTree, length);
return max;
}
// 构建前缀树
private Tree getPreTree(int[] nums, int length){
Tree root = new Tree();
for(int num : nums){
Tree p = root;
// 将num向右移动length-1位,相当于从最高位开始取依次放入,构建前缀树
for (int i = length - 1; i >= 0; i--){
if (((num >> i)&1) == 0){
if (p.left == null){
p.left = new Tree();
}
p = p.left;
}else {
if (p.right == null){
p.right = new Tree();
}
p = p.right;
}
}
}
return root;
}
public int searchMax(int[] nums, Tree root, int length){
int max = 0;
for (int num : nums) {
Tree p = root;
int ret = 0;
for (int i = length - 1; i >= 0; i--){
// 每位依次判断,如果是0,就匹配1,这样得到的值就会最大
if (((num >> i)&1) == 0){
if (p.right != null){
ret = ret * 2 + 1;
p = p.right;
}else {
ret *= 2;
p = p.left;
}
}else {
if (p.left != null){
ret = ret * 2 + 1;
p = p.left;
}else {
ret *= 2;
p = p.right;
}
}
}
if (ret > max)
max = ret;
}
return max;
}
}
总结: 还是想不到比较优秀的解法,不过通过这次巩固了位运算,以及了解到了前缀树的使用。