-1

Problem: Choose an element from the array to maximize the sum after XOR all elements in the array.

Input for problem statement: N=3 A=[15,11,8]

Output: 11

Approach: (15^15)+(15^11)+(15^8)=11

My Code for brute force approach:

def compute(N,A):
    ans=0
    for i in A:
      xor_sum=0
      for j in A:
        xor_sum+=(i^j)
      if xor_sum>ans:
          ans=xor_sum
    return ans

Above approach giving the correct answer but wanted to optimize the approach to solve it in O(n) time complexity. Please help me to get this.

1 Answers1

0

If you have integers with a fixed (constant) number of c bites then it should be possible because O(c) = O(1). For simplicity reasons I assume unsigned integers and n to be odd. If n is even then we sometimes have to check both paths in the tree (see solution below). You can adapt the algorithm to cover even n and negative numbers.

  1. find max in array with length n O(n)

  2. if max == 0 return 0 (just 0s in array)

  3. find the position p of the most significant bit of max O(c) = O(1)

     p = -1
     while (max != 0)
         p++
         max /= 2
    

    so 1 << p gives a mask for the highest set bit

  4. build a tree where the leaves are the numbers and every level stands for a position of a bit, if there is an edge to the left from the root then there is a number that has bit p set and if there is an edge to the right there is a number that has bit p not set, for the next level we have an edge to the left if there is a number with bit p - 1 set and an edge to the right if bit p - 1 is not set and so on, this can be done in O(cn) = O(n)

  5. go through the array and count how many times a bit at position i (i from 0 to p) is set => sum array O(cn) = O(n)

  6. assign the root of the tree to node x

  7. now for each i from p to 0 do the following:

    1. if x has only one edge => x becomes its only child node
    2. else if sum[i] > n / 2 => x becomes its right child node
    3. else x becomes its left child node

    in this step we choose the best path through the tree that gives us the most ones when xoring O(cn) = O(n)

  8. xor all the elements in the array with the value of x and sum them up to get the result, actually you could have built the result already in the step before by adding sum[i] * (1 << i) to the result if going left and (n - sum[i]) * (1 << i) if going right O(n)

All the sequential steps are O(n) and therefore overall the algorithm is also O(n).

maraca
  • 8,468
  • 3
  • 23
  • 45