If we combine both permutations, the result will have even parity when each permutation has the same parity, and odd parity if they have different parity. So if we solve the parity problem it's trivial to compare two different permutations.
Parity can be determined as follows: pick an arbitrary element, find the position that the permutation moves this to, repeat until you get back to the one you started with. You have now found a cycle: the permutation rotates all these elements round by one position. You need one swap less than the number of elements in the cycle to undo it. Now pick another element you haven't dealt with yet and repeat until you've seen every element. Observe that in total you needed one swap per element minus one swap per cycle.
Time complexity is O(N) in the size of the permutation. Note that although we have a loop within a loop, the inner loop can only ever iterate once for any element in the permutation.
def parity(permutation):
permutation = list(permutation)
length = len(permutation)
elements_seen = [False] * length
cycles = 0
for index, already_seen in enumerate(elements_seen):
if already_seen:
continue
cycles += 1
current = index
while not elements_seen[current]:
elements_seen[current] = True
current = permutation[current]
return (length-cycles) % 2 == 0
def arePermsEqualParity(perm0, perm1):
perm0 = list(perm0)
return parity([perm0[i] for i in perm1])
Also, just for fun, here's a much less efficient but much shorter implementation of the parity function based on the definition in Wikipedia (returning True for even and False for odd):
def parity(p):
return sum(
1 for (x,px) in enumerate(p)
for (y,py) in enumerate(p)
if x<y and px>py
)%2==0