逆序的概念大家都不陌生,它在行列式理论中是很重要的。
设 i 1 , i 2 , ⋯ , i n i_1,i_2,\cdots,i_n i1,i2,⋯,in是集合 { 1 , 2 , ⋯ , n } \{1,2,\cdots,n\} {1,2,⋯,n}的一个排列。如果 k < l k\lt l k<l且 i k > i l i_k\gt i_l ik>il,则称数对 ( i k , i l ) (i_k,i_l) (ik,il)为一个逆序。通俗地讲,一个排列中的逆序对应着不以自然顺序出现的一对数。例如 31524 31524 31524中的逆序有 ( 3 , 1 ) , ( 3 , 1 ) , ( 5 , 2 ) , ( 5 , 4 ) (3,1),(3,1),(5,2),(5,4) (3,1),(3,1),(5,2),(5,4)。显然集合 { 1 , 2 , ⋯ , n } \{1,2,\cdots,n\} {1,2,⋯,n}的自然顺序 12 ⋯ n 12\cdots n 12⋯n是唯一没有逆序的排列。
对于一个排列 i 1 , i 2 , ⋯ , i n i_1,i_2,\cdots,i_n i1,i2,⋯,in,令 a j a_j aj表示逆序对第二个成分为 j j j的逆序对数量,即 a j a_j aj表示在排列中在 j j j前面且大于 j j j的整数的个数。它度量 j j j的无序程度。
逆序列:数值序列 a 1 , a 2 , ⋯ , a n a_1,a_2,\cdots,a_n a1,a2,⋯,an叫做排列 i 1 , i 2 , ⋯ , i n i_1,i_2,\cdots,i_n i1,i2,⋯,in逆序列。 a 1 + a 2 + ⋯ + a n a_1+a_2+\cdots+a_n a1+a2+⋯+an度量一个排列的无序程度。例如 31524 31524 31524的逆序列为 1 , 2 , 0 , 1 , 0 1,2,0,1,0 1,2,0,1,0。
逆序列满足下面的条件:
0 ≤ a 1 ≤ n − 1 0 ≤ a 2 ≤ n − 2 ⋯ 0 ≤ a n − 1 ≤ 1 a n = 0 0\le a_1 \le n-1\\ 0\le a_2 \le n-2\\ \cdots \\ 0\le a_{n-1}\le 1\\ a_n = 0 0≤a1≤n−10≤a2≤n−2⋯0≤an−1≤1an=0
这个条件的原因很显然,对于每个 k = 1 , 2 , ⋯ , n k=1,2,\cdots, n k=1,2,⋯,n,在集合中存在 n − k n-k n−k个大于 k k k的整数。显然满足上述条件的序列个数等于 n ∗ ( n − 1 ) ∗ ⋯ 1 = n ! n*(n-1)*\cdots 1=n! n∗(n−1)∗⋯1=n!。这个数等于 { 1 , 2 , ⋯ , n } \{1,2,\cdots,n\} {1,2,⋯,n}的排列个数。
设 b 1 , b 2 , ⋯ , b n b_1,b_2,\cdots,b_n b1,b2,⋯,bn是满足下面条件的整数序列:
0 ≤ b 1 ≤ n − 1 0 ≤ b 2 ≤ n − 2 ⋯ 0 ≤ b n − 1 ≤ 1 b n = 0 0\le b_1 \le n-1\\ 0\le b_2 \le n-2\\ \cdots \\ 0\le b_{n-1}\le 1\\ b_n = 0 0≤b1≤n−10≤b2≤n−2⋯0≤bn−1≤1bn=0
那么,一定存在一个唯一一个 { 1 , 2 , ⋯ , n } \{1,2,\cdots,n\} {1,2,⋯,n}排列,它的逆序列是 b 1 , b 2 , ⋯ , b n b_1,b_2,\cdots,b_n b1,b2,⋯,bn。我们可以通过找到唯一构建逆序列的排列的方法来证明这个定理。
算法步骤如下:
通过上述步骤构建排列时,步骤 n , n − 1 , n − 2 , ⋯ , 1 n,n-1,n-2,\cdots,1 n,n−1,n−2,⋯,1根据逆序列 b 1 , b 2 , ⋯ , b n b_1,b_2,\cdots,b_n b1,b2,⋯,bn唯一确定 { 1 , 2 , ⋯ , n } \{1,2,\cdots,n\} {1,2,⋯,n}的一个排列。这个算法的缺点是:排列中的每一个整数的位置不到最后是不得而知的,算法在执行的过程中只做到了这些整数的相对位置保持固定。
例子:构建 { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } \{1,2,3,4,5,6,7,8\} {1,2,3,4,5,6,7,8}的一个排列,使其逆序列是 5 , 3 , 4 , 0 , 2 , 1 , 1 , 0 5,3,4,0,2,1,1,0 5,3,4,0,2,1,1,0。根据上述算法:
8 : 8 7 : 87 6 : 867 5 : 8657 4 : 48657 3 : 486537 2 : 4862537 1 : 48625137 \begin{aligned} &8:8\\ &7:87\\ &6:867\\ &5:8657\\ &4:48657\\ &3:486537\\ &2:4862537\\ &1:48625137 \end{aligned} 8:87:876:8675:86574:486573:4865372:48625371:48625137
python实现起来也比较容易:
def generate_algo1(seq):
permutation = []
for i in range(len(seq), 0, -1):
permutation.insert(int(seq[i-1]), i)
return permutation
seq = input().split()
print(generate_algo1(seq))
输入:5 3 4 0 2 1 1 0
输出:[4, 8, 6, 2, 5, 1, 3, 7]
我们从 n n n个空位置上出发,把这些空位置从左到右标记上 1 , 2 , ⋯ , n 1,2,\cdots, n 1,2,⋯,n。算法步骤如下:
这种方法中, 1 , 2 , ⋯ , n 1,2,\cdots,n 1,2,⋯,n在排列中的位置是确定的。依旧用上述例子 5 , 3 , 4 , 0 , 2 , 1 , 1 , 0 5,3,4,0,2,1,1,0 5,3,4,0,2,1,1,0来过一遍该算法:
1 : _ _ _ _ _ 1 _ _ 2 : _ _ _ 2 _ 1 _ _ 3 : _ _ _ 2 _ 1 3 _ 4 : 4 _ _ 2 _ 1 3 _ 5 : 4 _ _ 2 5 1 3 _ 6 : 4 _ 6 2 5 1 3 _ 7 : 4 _ 6 2 5 1 3 7 8 : 4 8 6 2 5 1 3 7 \begin{aligned} &1:\_ \ \_\ \_\ \_\ \_\ 1\ \_\ \_\\ &2:\_ \ \_\ \_\ 2\ \_\ 1\ \_\ \_\\ &3:\_ \ \_\ \_\ 2\ \_\ 1\ 3\ \_\\ &4:4 \ \_\ \_\ 2\ \_\ 1\ 3\ \_\\ &5:4 \ \_\ \_\ 2\ 5\ 1\ 3\ \_\\ &6:4 \ \_\ 6\ 2\ 5\ 1\ 3\ \_\\ &7:4 \ \_\ 6\ 2\ 5\ 1\ 3\ 7\\ &8:4 \ 8\ 6\ 2\ 5\ 1\ 3\ 7\\ \end{aligned} 1:_ _ _ _ _ 1 _ _2:_ _ _ 2 _ 1 _ _3:_ _ _ 2 _ 1 3 _4:4 _ _ 2 _ 1 3 _5:4 _ _ 2 5 1 3 _6:4 _ 6 2 5 1 3 _7:4 _ 6 2 5 1 3 78:4 8 6 2 5 1 3 7
python实现:
def generate_algo2(seq):
n = len(seq)
permutation = [None]*n
for i in range(1, n+1):
j, k = 0, int(seq[i-1]) + 1
while j < n:
if not permutation[j]:
k -= 1
if k == 0:
permutation[j] = i
break
j += 1
return permutation
输入:5 3 4 0 2 1 1 0
输出:[4, 8, 6, 2, 5, 1, 3, 7]
习惯上,按照某个排列中的逆序个数是偶数还是奇数而把 { 1 , 2 , ⋯ , n } \{1,2,\cdots, n\} {1,2,⋯,n}的这个排列 i 1 i 2 ⋯ i n i_1i_2\cdots i_n i1i2⋯in称为偶排列或奇排列。排列的符号按照排列是偶排列还是奇排列而定义为 + 1 , − 1 +1,-1 +1,−1。行列式的定义就包含了这一点, n ∗ n n*n n∗n的矩阵 A = [ a i j ] ( i = 1 , 2 , ⋯ , n ) A=[a_{ij}](i=1,2,\cdots,n) A=[aij](i=1,2,⋯,n),其行列式为
d e t ( A ) = ∑ ε ( i 1 i 2 ⋯ i n ) a 1 i 1 a 2 i 2 ⋯ a n i n det(A)=\sum \varepsilon(i_1i_2\cdots i_n)a_{1i_1}a_{2i_2}\cdots a_{ni_n} det(A)=∑ε(i1i2⋯in)a1i1a2i2⋯anin
其中 ε ( i 1 i 2 ⋯ i n ) \varepsilon(i_1i_2\cdots i_n) ε(i1i2⋯in)为 i 1 i 2 ⋯ i n i_1i_2\cdots i_n i1i2⋯in的符号。
如果排列 i 1 i 2 ⋯ i n i_1i_2\cdots i_n i1i2⋯in有逆序列 b 1 , b 2 , ⋯ , b n b_1,b_2,\cdots,b_n b1,b2,⋯,bn且 k = b 1 + b 2 + ⋯ + b n k=b_1+b_2+\cdots +b_n k=b1+b2+⋯+bn为逆序数,那么可以通过连续 k k k次交换相邻两个数而把 i 1 i 2 ⋯ i n i_1i_2\cdots i_n i1i2⋯in转化成 12 ⋯ n 12\cdots n 12⋯n。步骤为:
例子:交换 361245 361245 361245到 123456 123456 123456。
361245 316245 136245 132645 123645 123465 123456 361245\\ 316245\\ 136245\\ 132645\\ 123645\\ 123465\\ 123456 361245316245136245132645123645123465123456