提问者:小点点

有可能用线性时间计算排列的符号吗?


我只是想知道是否有一种方法可以在线性(或至少比n^2更好?)时间内计算排列的符号

例如,假设我有一个n个数字的数组,我在这个数组中置换两个元素,这将翻转排列的符号。我有一个函数可以在n^2时间内计算它,然而,似乎有一个更有效的算法。

我附上了一个二次时间计算的最小可重现示例,

import numpy as np

vals = np.arange(1,6,1)
pvals = np.arange(1,6,1)
pvals[0], pvals[1] = pvals[1], pvals[0] #swap

def quadratic(vals):
  sgn_matrix = np.sign(np.expand_dims(vals, -1) - np.expand_dims(vals, -2))
  return np.prod(np.tril(np.ones_like(sgn_matrix)) + np.triu(sgn_matrix, 1))

def sub_quadratic(vals):
  #algorithm quicker than quadratic time?

sgn = quadratic(vals)
print(sgn)   #prints +1 

psgn = quadratic(pvals)
print(psgn)  #prints -1 (because one permutation)

我环顾了一下SO(例如这里),人们一直在谈论循环排列,这种排列显然可以在线性时间内计算,但这是我完全没有意识到的,也找不到太多关于我自己的东西。

太长别读有人知道一种计算次二次时间排列符号的方法吗?


共1个答案

匿名用户

只需将其分解为换位并检查您是否需要偶数或奇数个换位:

def permutation_sign(perm):
    parity = 1
    perm = perm.copy()
    for i in range(len(perm)):
        while perm[i] != i+1:
            parity *= -1
            j = perm[i] - 1
            # Note: if you try to inline the j computation into the next line,
            # you'll get evaluation order bugs.
            perm[i], perm[j] = perm[j], perm[i]
    return parity