Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1829. Maximum XOR for Each Query - Leetcode Solution

Code Implementation

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;
};
      

Problem Description

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:

  • Each query considers the array after removing the last element from the previous array.
  • For each query, choose a k in the range [0, 2^maximumBit - 1].
  • Return an array of k values, one for each query, in order.

Thought Process

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.

Solution Approach

  • Step 1: Compute the XOR of the entire array nums. This is the starting currXor for the first query.
  • Step 2: The maximum value possible with maximumBit is maxNum = 2^maximumBit - 1.
  • Step 3: For each query, the optimal k is currXor ^ maxNum. This ensures that every bit is flipped, maximizing the XOR result.
  • Step 4: After each query, update currXor by removing nums[i] (i.e., currXor ^= nums[i]), since the next query uses the array with one less element.
  • Step 5: Repeat this process for each query (from the end of the array to the start), collecting the k values.

This approach only requires a single pass through the array and simple bitwise operations, making it highly efficient.

Example Walkthrough

Let's use nums = [0,1,1,3] and maximumBit = 2 as an example.

  • Step 1: Calculate the initial XOR: 0 ^ 1 ^ 1 ^ 3 = 3.
  • Step 2: maxNum = 2^2 - 1 = 3.
  • First Query: currXor = 3. k = 3 ^ 3 = 0. Append 0.
  • Remove last element (3): currXor = 3 ^ 3 = 0.
  • Second Query: currXor = 0. k = 0 ^ 3 = 3. Append 3.
  • Remove last element (1): currXor = 0 ^ 1 = 1.
  • Third Query: currXor = 1. k = 1 ^ 3 = 2. Append 2.
  • Remove last element (1): currXor = 1 ^ 1 = 0.
  • Fourth Query: currXor = 0. k = 0 ^ 3 = 3. Append 3.

The final answer is [0, 3, 2, 3].

Time and Space Complexity

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:

  • Compute the initial XOR in O(n) time.
  • For each query, do a constant-time calculation and update, totaling O(n) time.

Thus, the overall time complexity is O(n).

Space complexity is O(n) for the result array.

Summary

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.