每个查询的最大异或值
难度:
标签:
题目描述
代码结果
运行时间: 61 ms, 内存: 31.2 MB
/*
* 题目思路:
* 1. 对于每次查询,我们需要找到一个 k,使得 (nums 中所有元素 XOR k) 的值最大化。
* 2. k 的范围是 0 到 2^maximumBit - 1。
* 3. 要使 XOR 结果最大,我们需要尽可能设置 k 的二进制位为 1。
* 4. 我们可以通过计算当前数组的 XOR 总和 prefixXOR,然后 k 可以通过 (2^maximumBit - 1) ^ prefixXOR 得到。
* 5. 使用 Java Stream 的方式实现。
*/
import java.util.stream.IntStream;
public class Solution {
public int[] getMaximumXor(int[] nums, int maximumBit) {
int n = nums.length;
int maxNum = (1 << maximumBit) - 1; // 2^maximumBit - 1
int prefixXOR = IntStream.of(nums).reduce(0, (a, b) -> a ^ b);
int[] answer = new int[n];
IntStream.range(0, n).forEach(i -> {
answer[i] = maxNum ^ prefixXOR;
prefixXOR ^= nums[n - 1 - i];
});
return answer;
}
}
解释
方法:
这个题解使用了前缀异或和的思路,从而避免了对数组进行实际的元素删除操作。首先,通过遍历整个数组,计算从第一个元素到当前元素的所有异或和,并存储到变量 x_or 中。利用异或操作的性质,x_or 可以在常数时间内通过上一个 x_or 值和当前元素进行更新。然后为了找到每一步的最大值,我们需要找到一个 k 值,使得 x_or XOR k 的结果最大。为了达到这一点,我们可以将 x_or 与 (1 << maximumBit) - 1 进行异或操作,该值实际上是在 maximumBit 位都为1的最大数字,这样可以确保异或结果的最大化。结果数组在完成遍历后需要反转,以匹配题目中逐步删除元素的顺序。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在计算最大异或结果时,使用 `x_or ^ max_num` 能保证得到最大值?
▷🦆
在这个算法中,`max_num` 的计算方法 `(1 << maximumBit) - 1` 是基于什么原理?为什么它能够覆盖所有小于 `2^maximumBit` 的 k 值?
▷🦆
为什么最终结果数组 `ans` 需要进行反转操作?这与逐步删除数组元素的操作有什么直接关系?
▷