假设我有以下数组:
[6,3,3,5,6],
是否有一种已经实现的方法对数组进行排序,并且还返回了使算法对其进行排序所需的排列数?
例如,我必须向右移动3次,因为它可以被订购,这样可以得到奇偶校验-1。
一般的问题是订购一个任意数组(所有整数,重复索引!),并知道算法执行的奇偶校验以对数组进行排序。
答案 0 :(得分:2)
a=[6,3,3,5,6]
sortperm(a) - [ 1:size(a)[1] ]
结果
3-element Array{Int64,1}:
1
1
1
-3
0
sortperm
显示每个第n个索引应该进入的位置。我们使用1:size(a)[1]
将早期索引与其原始索引进行比较。
答案 1 :(得分:2)
如果数组很小,则可以计算置换矩阵的行列式
function permutation_sign_1(p)
n = length(p)
A = zeros(n,n)
for i in 1:n
A[i,p[i]] = 1
end
det(A)
end
通常,您可以将排列分解为循环的乘积, 计算偶数周期数,并返回其奇偶校验。
function permutation_sign_2(p)
n = length(p)
not_seen = Set{Int}(1:n)
seen = Set{Int}()
cycles = Array{Int,1}[]
while ! isempty(not_seen)
cycle = Int[]
x = pop!( not_seen )
while ! in(x, seen)
push!( cycle, x )
push!( seen, x )
x = p[x]
pop!( not_seen, x, 0 )
end
push!( cycles, cycle )
end
cycle_lengths = map( length, cycles )
even_cycles = filter( i -> i % 2 == 0, cycle_lengths )
length( even_cycles ) % 2 == 0 ? 1 : -1
end
排列的奇偶性也可以从
反转次数。
可以通过稍微修改合并排序算法来计算它。
因为它也用于计算肯德尔的tau(检查less(corkendall)
),
已经有了实施。
using StatsBase
function permutation_sign_3(p)
x = copy(p)
number_of_inversions = StatsBase.swaps!(x)
number_of_inversions % 2 == 0 ? +1 : -1
end
在你的例子中,这三个函数给出了相同的结果:
x = [6,3,3,5,6]
p = sortperm(x)
permutation_sign_1( p )
permutation_sign_2( p )
permutation_sign_3( p ) # -1