{x}
blog image

Find XOR Sum of All Pairs Bitwise AND

The XOR sum of a list is the bitwise XOR of all its elements. If the list only contains one element, then its XOR sum will be equal to this element.

  • For example, the XOR sum of [1,2,3,4] is equal to 1 XOR 2 XOR 3 XOR 4 = 4, and the XOR sum of [3] is equal to 3.

You are given two 0-indexed arrays arr1 and arr2 that consist only of non-negative integers.

Consider the list containing the result of arr1[i] AND arr2[j] (bitwise AND) for every (i, j) pair where 0 <= i < arr1.length and 0 <= j < arr2.length.

Return the XOR sum of the aforementioned list.

 

Example 1:

Input: arr1 = [1,2,3], arr2 = [6,5]
Output: 0
Explanation: The list = [1 AND 6, 1 AND 5, 2 AND 6, 2 AND 5, 3 AND 6, 3 AND 5] = [0,1,2,0,2,1].
The XOR sum = 0 XOR 1 XOR 2 XOR 0 XOR 2 XOR 1 = 0.

Example 2:

Input: arr1 = [12], arr2 = [4]
Output: 4
Explanation: The list = [12 AND 4] = [4]. The XOR sum = 4.

 

Constraints:

  • 1 <= arr1.length, arr2.length <= 105
  • 0 <= arr1[i], arr2[j] <= 109

Solution Explanation:

This problem asks to find the XOR sum of all pairs' bitwise AND results from two input arrays, arr1 and arr2. A naive approach would involve iterating through all pairs, calculating the bitwise AND, and then XORing the results. This would have a time complexity of O(n*m), where n and m are the lengths of arr1 and arr2 respectively. However, a significantly more efficient solution exists leveraging bitwise properties.

Optimal Approach:

The key observation is that the XOR operation is associative and commutative. Let's denote the XOR sum of arr1 as xor_arr1 and the XOR sum of arr2 as xor_arr2. The solution hinges on the following mathematical equivalence:

The XOR sum of all pairs' bitwise AND results is equivalent to the bitwise AND of the XOR sums of the individual arrays. In other words:

Result = xor_arr1 & xor_arr2

This dramatically reduces the computational complexity. We first calculate the XOR sum of each array independently and then perform a single bitwise AND operation on the two results.

Time Complexity Analysis:

  • Calculating xor_arr1 and xor_arr2 takes O(n) and O(m) time respectively, where n is the length of arr1 and m is the length of arr2.
  • The bitwise AND operation takes constant time, O(1).

Therefore, the overall time complexity of the optimized solution is O(n + m), which is linear and significantly better than the naive O(n*m) approach.

Space Complexity Analysis:

The algorithm uses only a few constant extra variables to store intermediate results (a, b, xor_arr1, xor_arr2 etc). Thus, the space complexity is O(1), which is constant.

Code Implementation in Different Languages:

Python3:

from functools import reduce
import operator
 
class Solution:
    def getXORSum(self, arr1: List[int], arr2: List[int]) -> int:
        xor_arr1 = reduce(operator.xor, arr1, 0)  #Efficient XOR sum calculation
        xor_arr2 = reduce(operator.xor, arr2, 0)
        return xor_arr1 & xor_arr2
 

Java:

class Solution {
    public int getXORSum(int[] arr1, int[] arr2) {
        int xor_arr1 = 0;
        for (int num : arr1) {
            xor_arr1 ^= num;
        }
        int xor_arr2 = 0;
        for (int num : arr2) {
            xor_arr2 ^= num;
        }
        return xor_arr1 & xor_arr2;
    }
}

C++:

#include <numeric>
#include <vector>
 
class Solution {
public:
    int getXORSum(std::vector<int>& arr1, std::vector<int>& arr2) {
        int xor_arr1 = std::accumulate(arr1.begin(), arr1.end(), 0, std::bit_xor<int>());
        int xor_arr2 = std::accumulate(arr2.begin(), arr2.end(), 0, std::bit_xor<int>());
        return xor_arr1 & xor_arr2;
    }
};

Go:

func getXORSum(arr1 []int, arr2 []int) int {
	xor_arr1 := 0
	for _, num := range arr1 {
		xor_arr1 ^= num
	}
	xor_arr2 := 0
	for _, num := range arr2 {
		xor_arr2 ^= num
	}
	return xor_arr1 & xor_arr2
}

TypeScript:

function getXORSum(arr1: number[], arr2: number[]): number {
    const xor_arr1 = arr1.reduce((acc, curr) => acc ^ curr, 0);
    const xor_arr2 = arr2.reduce((acc, curr) => acc ^ curr, 0);
    return xor_arr1 & xor_arr2;
}

All these implementations follow the optimized approach, achieving a linear time complexity and constant space complexity. The choice of language only affects the syntax, not the core algorithm.