Observe that if A[i]^A[j] == x
, this implies that A[i]^x == A[j]
and A[j]^x == A[i]
.
So, an O(n) solution would be to iterate through an associate map (dict
) where each key is an item from A
and each value is the respective count of the item. Then, for each item, calculate A[i]^x
, and see if A[i]^x
is in the map. If it is in the map, this implies that A[i]^A[j] == x
for some j
. Since we have a map with the count of all items that equal A[j]
, the total number of pairs will be num_Ai * num_Aj
. Note that each element will be counted twice since XOR is commutative (i.e. A[i]^A[j] == A[j]^A[i]
), so we have to divide the final count by 2 since we've double counted each pair.
def create_count_map(lst):
result = {}
for item in lst:
if item in result:
result[item] += 1
else:
result[item] = 1
return result
def get_count(lst, x):
count_map = create_count_map(lst)
total_pairs = 0
for item in count_map:
xor_res = item ^ x
if xor_res in count_map:
total_pairs += count_map[xor_res] * count_map[item]
return total_pairs // 2
print(get_count([3, 6, 8, 10, 15, 50], 5))
print(get_count([1, 3, 1, 3, 1], 2))
outputs
2
6
as desired.
Why is this O(n)?
Converting a list
to a dict
s.t. the dict contains the count of each item in the list is O(n) time.
Calculating item ^ x
is O(1) time, and calculating whether this result is in a dict
is also O(1) time. dict
key access is also O(1), and so is multiplication of two elements. We do all this n times, hence O(n) time for the loop.
O(n) + O(n) reduces to O(n) time.
Edited to handle duplicates correctly.