在朱莉娅排序与奇偶校验

时间:2015-06-22 18:49:01

标签: julia

假设我有以下数组:

[6,3,3,5,6],

是否有一种已经实现的方法对数组进行排序,并且还返回了使算法对其进行排序所需的排列数?

例如,我必须向右移动3次,因为它可以被订购,这样可以得到奇偶校验-1。

一般的问题是订购一个任意数组(所有整数,重复索引!),并知道算法执行的奇偶校验以对数组进行排序。

2 个答案:

答案 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