class Solution:
def getMaximumXor(self, nums, maximumBit):
n = len(nums)
result = []
prefix_xor = 0
for num in nums:
prefix_xor ^= num
max_num = (1 << maximumBit) - 1
for i in range(n-1, -1, -1):
result.append(prefix_xor ^ max_num)
prefix_xor ^= nums[i]
return result
class Solution {
public:
vector<int> getMaximumXor(vector<int>& nums, int maximumBit) {
int n = nums.size();
vector<int> result;
int prefix_xor = 0;
for (int num : nums) prefix_xor ^= num;
int max_num = (1 << maximumBit) - 1;
for (int i = n - 1; i >= 0; --i) {
result.push_back(prefix_xor ^ max_num);
prefix_xor ^= nums[i];
}
return result;
}
};
class Solution {
public int[] getMaximumXor(int[] nums, int maximumBit) {
int n = nums.length;
int[] result = new int[n];
int prefixXor = 0;
for (int num : nums) prefixXor ^= num;
int maxNum = (1 << maximumBit) - 1;
for (int i = n - 1; i >= 0; --i) {
result[n - 1 - i] = prefixXor ^ maxNum;
prefixXor ^= nums[i];
}
return result;
}
}
var getMaximumXor = function(nums, maximumBit) {
let n = nums.length;
let result = [];
let prefixXor = 0;
for (let num of nums) prefixXor ^= num;
let maxNum = (1 << maximumBit) - 1;
for (let i = n - 1; i >= 0; --i) {
result.push(prefixXor ^ maxNum);
prefixXor ^= nums[i];
}
return result;
};
Given an array nums
and an integer maximumBit
, you are to answer a series of queries. For each query (starting from the whole array, then removing the last element one by one), you must find an integer k
(where 0 <= k < 2^maximumBit
) such that (current XOR of all elements) XOR k
is maximized. For every query, return this k
.
Key constraints:
k
in the range [0, 2^maximumBit - 1]
.k
values, one for each query, in order.
The problem asks us to maximize the XOR result for a given prefix of the array, at each step, by choosing an optimal k
. The brute-force approach would be to try every possible k
for each query, but this is inefficient, especially since maximumBit
can be up to 20, leading to up to a million possible k
values per query.
Instead, let's consider what it means to maximize currXor ^ k
. Since k
can be any number with up to maximumBit
bits, the maximum possible value we can get is 2^maximumBit - 1
. To achieve this, we want currXor ^ k = 2^maximumBit - 1
, which means k = currXor ^ (2^maximumBit - 1)
.
We also realize that for each query, the new currXor
can be computed efficiently by removing the last element using XOR, since XOR is its own inverse.
nums
. This is the starting currXor
for the first query.
maximumBit
is maxNum = 2^maximumBit - 1
.
k
is currXor ^ maxNum
. This ensures that every bit is flipped, maximizing the XOR result.
currXor
by removing nums[i]
(i.e., currXor ^= nums[i]
), since the next query uses the array with one less element.
k
values.
This approach only requires a single pass through the array and simple bitwise operations, making it highly efficient.
Let's use nums = [0,1,1,3]
and maximumBit = 2
as an example.
0 ^ 1 ^ 1 ^ 3 = 3
.
maxNum = 2^2 - 1 = 3
.
currXor = 3
. k = 3 ^ 3 = 0
. Append 0.
currXor = 3 ^ 3 = 0
.
currXor = 0
. k = 0 ^ 3 = 3
. Append 3.
currXor = 0 ^ 1 = 1
.
currXor = 1
. k = 1 ^ 3 = 2
. Append 2.
currXor = 1 ^ 1 = 0
.
currXor = 0
. k = 0 ^ 3 = 3
. Append 3.
The final answer is [0, 3, 2, 3]
.
Brute-force approach: For every query, try all possible k
in [0, 2^maximumBit-1]
. For n
queries, that's O(n * 2^{maximumBit})
time, which is infeasible for large maximumBit
.
Optimized approach: We only need to:
O(n)
time.O(n)
time.Thus, the overall time complexity is O(n).
Space complexity is O(n) for the result array.
The key insight is realizing that to maximize currXor ^ k
, you want k
to flip all bits of currXor
within the allowed bit range. This leads to a very efficient, linear-time solution that only uses simple bitwise operations and one pass through the array. The approach is elegant because it leverages XOR properties and avoids unnecessary brute-force computation.