I have a positive integer array- {1,5,8,2,10} and a given value 7. I need to find whether a subset of the array exists such that the XOR of its elements is the value 7. In this case the subset is {5,2} because 5 xor 2 is 7. One naive solution is to find all the subsets and check whether a solution exist.I want some algorithm better than the naive. NOTE:-I just need to find whether a solution exists or not.I don't need to find the subset.
Asked
Active
Viewed 3,468 times
6
-
just an idea : sort your array, this way you'll have to check the sums until numbers less than 7. – mounaim Dec 06 '14 at 14:43
-
3"Efficient"...? Time, memory, theoretical complexity? – deviantfan Dec 06 '14 at 14:49
-
1@mounaim Are you saying that numbers >7 can´t be part of the solution? Wrong. – deviantfan Dec 06 '14 at 14:50
-
1I assume he is working with positive integers – mounaim Dec 06 '14 at 14:55
-
2@mounaim And...? 15 xor 8 is 7 too, and both are >7 (the shown array has no 15 and 8, but it should work with any array and number, right?) – deviantfan Dec 06 '14 at 14:57
-
1Gaussian elimination over GF(2) would be linear-time (sort of a cheat because I'm treating 32 as a constant). – David Eisenstat Dec 06 '14 at 15:02
-
@David that would be the answer I guess, you might need to add some context for the non-mathematicians though ;-) – Vincent van der Weele Dec 06 '14 at 15:20
-
@deviantfan 5, 8, and 10 would be a second solution. – Teepeemm Dec 06 '14 at 16:49
-
I feel this problem is NP complete and there is no polynomial time solution. We can reduce subset sum (http://en.wikipedia.org/wiki/Subset_sum_problem) problem to this problem to prove this is NP complete. – Diptendu Dec 06 '14 at 17:07
1 Answers
8
This boils down to solving a system of linear equations over the finite field with two elements (GF(2)). Bitwise XOR here is equivalent to adding two vectors. The sample inputs correspond to vectors like so.
1: 0001
5: 0101
8: 1000
2: 0010
10: 1010
7: 0111
The system looks like this.
[0 0 1 0 1] [a] [0]
[0 1 0 0 0] [b] [1]
[0 0 0 1 1] [c] = [1]
[1 1 0 0 0] [d] [1]
[e]
The following Python code uses Gaussian elimination and is implemented using bitwise operations. For fixed-width integers, it runs in linear time. Forgive me for not reexplaining Gaussian elimination when there are a million better treatments on the Internet already.
#!/usr/bin/env python3
def least_bit_set(x):
return x & (-x)
def delete_zeros_from(values, start):
i = start
for j in range(start, len(values)):
if values[j] != 0:
values[i] = values[j]
i += 1
del values[i:]
def eliminate(values):
values = list(values)
i = 0
while True:
delete_zeros_from(values, i)
if i >= len(values):
return values
j = i
for k in range(i + 1, len(values)):
if least_bit_set(values[k]) < least_bit_set(values[j]):
j = k
values[i], values[j] = (values[j], values[i])
for k in range(i + 1, len(values)):
if least_bit_set(values[k]) == least_bit_set(values[i]):
values[k] ^= values[i]
i += 1
def in_span(x, eliminated_values):
for y in eliminated_values:
if least_bit_set(y) & x != 0:
x ^= y
return x == 0
def main():
values = [1, 5, 8, 2, 10]
eliminated_values = eliminate(values)
print(eliminated_values)
x = int(input())
print(in_span(x, eliminated_values))
if __name__ == '__main__':
main()

David Eisenstat
- 64,237
- 7
- 60
- 120
-
Is there any better way when we know that the maximum number of bits of any number in the array can go upto 10 only? – user3522401 Dec 06 '14 at 20:25
-
Can there be a recursive solution just like the subset sum problem? – user3522401 Dec 07 '14 at 12:52
-
Does this code tell if a solution exists, and if yes, then how many? – Sahil Arora Dec 12 '15 at 19:39
-
@SahilArora Yes to your first question, no to your second. The modification would be to multiply the number of solutions by two every time a zero that is not the pivot element is deleted. – David Eisenstat Dec 14 '15 at 00:00