Taro Logo

Maximum XOR for Each Query

Medium
Google logo
Google
1 view
Topics:
ArraysBit Manipulation

You are given a sorted array nums of n non-negative integers and an integer maximumBit. You want to perform the following query n times:

  1. Find a non-negative integer k < 2^maximumBit such that nums[0] XOR nums[1] XOR ... XOR nums[nums.length-1] XOR k is maximized. k is the answer to the i^{th} query.
  2. Remove the last element from the current array nums.

Return an array answer, where answer[i] is the answer to the i^{th} query.

For example, given the input nums = [0,1,1,3] and maximumBit = 2, the expected output is [0,3,2,3]. The queries are answered as follows:

  1. nums = [0,1,1,3], k = 0 since 0 XOR 1 XOR 1 XOR 3 XOR 0 = 3.
  2. nums = [0,1,1], k = 3 since 0 XOR 1 XOR 1 XOR 3 = 3.
  3. nums = [0,1], k = 2 since 0 XOR 1 XOR 2 = 3.
  4. nums = [0], k = 3 since 0 XOR 3 = 3.

As another example, if nums = [2,3,4,7] and maximumBit = 3, the expected output is [5,2,6,5].

Write a function that efficiently solves this problem.

Solution


Naive Approach

The naive approach is to iterate through the array for each query, calculate the XOR sum, and then find the k that maximizes the XOR sum with k < 2^maximumBit. After each query, we remove the last element from the array.

Code:

def get_max_xor(nums, maximumBit):
    xor_sum = 0
    for num in nums:
        xor_sum ^= num
    
    max_xor = (1 << maximumBit) - 1
    return max_xor ^ xor_sum

def solve_naive(nums, maximumBit):
    answer = []
    while nums:
        k = get_max_xor(nums, maximumBit)
        answer.append(k)
        nums.pop()
    return answer

Time Complexity

O(n^2), since for each of the n queries we iterate over the remaining n elements of the array.

Space Complexity

O(n), the space used for the answer array.

Optimal Approach

We can optimize this by calculating the XOR sum of the entire array only once and then updating it as we remove elements.

  1. Calculate the initial XOR sum of all elements in nums. This is done only once.
  2. For each query:
    • Calculate k as (2^maximumBit - 1) XOR current_xor_sum
    • Add k to the answer array
    • Remove the last element from nums
    • Update current_xor_sum by XORing it with the removed element

Code:

def solve_optimal(nums, maximumBit):
    answer = []
    xor_sum = 0
    for num in nums:
        xor_sum ^= num
    
    for _ in range(len(nums)):
        max_xor = (1 << maximumBit) - 1
        k = max_xor ^ xor_sum
        answer.append(k)
        xor_sum ^= nums.pop()
    return answer

Time Complexity

O(n), as we iterate through the array only once to calculate the initial XOR sum and then iterate n times for the queries, each time doing constant time operations.

Space Complexity

O(1), excluding the output array. The space used is constant because we are only using a few variables to store the XOR sum and intermediate results.

Edge Cases

  • Empty Array: If the input array is empty, the initial XOR sum will be 0. The algorithm should still work correctly.
  • Maximum Bit is 1: The algorithm should correctly handle the case where maximumBit is 1. In this case, k will be either 0 or 1.
  • Large Array: The algorithm should handle large arrays efficiently due to its linear time complexity.