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.