Если мы объединим обе перестановки, результат будет иметь четную четность, когда каждая перестановка имеет одинаковую четность, и нечетную четность, если они имеют разную четность. Так что, если мы решим проблему четности , будет тривиально сравнить две разные перестановки.
Четность можно определить следующим образом: выберите произвольный элемент, найдите позицию, на которую перестановка переместит это, повторяйте, пока не вернетесь к тому, с которого вы начали. Теперь вы нашли цикл: перестановка вращает все эти элементы вокруг одной позиции. Вам нужно на один обмен меньше, чем количество элементов в цикле, чтобы отменить его. Теперь выберите другой элемент, с которым вы еще не работали, и повторяйте, пока не увидите каждый элемент. Обратите внимание, что всего вам понадобился один своп на элемент минус один своп за цикл.
Сложность времени составляет O (N) в размере перестановки. Обратите внимание, что хотя у нас есть цикл внутри цикла, внутренний цикл может повторяться только один раз для любого элемента в перестановке.
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])
Кроме того, просто для забавы, вот гораздо менее эффективная, но гораздо более короткая реализация функции четности, основанная на определении в Википедии (возвращающей True для четного и False для нечетного):
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