Steinhaus–Johnson–Trotter algorithm 允许在排列生成期间轻松保持反转计数。维基摘录:
Thus, from the single permutation on one element,
1
one may place the number 2 in each possible position in descending
order to form a list of two permutations on two elements,
1 2
2 1
Then, one may place the number 3 in each of three different positions
for these three permutations, in descending order for the first
permutation 1 2, and then in ascending order for the permutation 2 1:
1 2 3
1 3 2
3 1 2
3 2 1
2 3 1
2 1 3
在递归的每一步,我们都会在较小的数字列表中插入最大的数字。很明显,这个插入增加了 M 个新的反转,其中 M 是插入位置(从右数)。例如,如果我们有 3 1 2 列表(2 个反转),并且将插入 4
3 1 2 4 //position 0, 2 + 0 = 2 inversions
3 1 4 2 //position 1, 2 + 1 = 3 inversions
3 4 1 2 //position 2, 2 + 2 = 4 inversions
4 3 1 2 //position 3, 2 + 3 = 5 inversions
伪代码:
function Generate(List, Count)
N = List.Length
if N = N_Max then
Output(List, 'InvCount = ': Count)
else
for Position = 0 to N do
Generate(List.Insert(N, N - Position), Count + Position)
附:递归方法在这里不是强制性的,但我怀疑它对于功能性的人来说是很自然的
P.P.S如果您担心插入到列表中,请考虑 Even's speedup section,它仅使用相邻元素的交换,并且每次交换都会增加或减少反转计数 1。