1 逆序
逆序的概念大家都不陌生,它在行列式理论中是很重要的。
设 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}的排列个数。
2 定理
设
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。我们可以通过找到唯一构建逆序列的排列的方法来证明这个定理。
算法1:从逆序构建一个排列
算法步骤如下:
- n n n:写出 n n n。
- n − 1 n-1 n−1:考虑 b n − 1 b_{n-1} bn−1。我们知道 0 ≤ b n − 1 ≤ 1 0\le b_{n-1}\le 1 0≤bn−1≤1。如果 b n − 1 = 0 b_{n-1}=0 bn−1=0,则 n − 1 n-1 n−1应该放在 n n n的前面。如果 b n − 1 = 1 b_{n-1}=1 bn−1=1,则 n − 1 n-1 n−1应该放在 n n n的后面。
- n − 2 n-2 n−2:考虑 b n − 2 b_{n-2} bn−2。类似地,我们知道 0 ≤ b n − 1 ≤ 2 0\le b_{n-1}\le 2 0≤bn−1≤2。如果 b n − 2 = 0 b_{n-2}=0 bn−2=0,则 n − 2 n-2 n−2应该放在上一步构建完的两个数的前面。如果 b n − 2 = 1 b_{n-2}=1 bn−2=1,则 n − 2 n-2 n−2应该放在两个数的中间。如果 b n − 2 = 0 b_{n-2}=0 bn−2=0,则 n − 2 n-2 n−2应该放在两个数的后面。
- ⋯ ⋯ \cdots \cdots ⋯⋯
- n − k n-k n−k:(一般步骤)我们知道 0 ≤ b n − k ≤ k 0\le b_{n-k}\le k 0≤bn−k≤k,从步骤 n n n到步骤 n − k + 1 n-k+1 n−k+1中, k k k个数 n , n − 1 , ⋯ , n − k + 1 n,n-1,\cdots,n-k+1 n,n−1,⋯,n−k+1的顺序都已经排好了。如果 b n − k = 0 b_{n-k}=0 bn−k=0则放在最前面 … … \dots\dots ……如果 b n − k = k b_{n-k}=k bn−k=k则放在最后面。
- ⋯ ⋯ \cdots \cdots ⋯⋯
- 1 1 1:我们必须把 1 1 1放在上一步所构造的序列的第 b 1 b_1 b1个数的后面。
通过上述步骤构建排列时,步骤 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]
算法2:从逆序列构建一个排列
我们从 n n n个空位置上出发,把这些空位置从左到右标记上 1 , 2 , ⋯ , n 1,2,\cdots, n 1,2,⋯,n。算法步骤如下:
- 1 1 1:因为在这个排列中 1 1 1之前有 b 1 b_1 b1个整数,所以必须把 1 1 1放在位置标签为 b 1 + 1 b_1 + 1 b1+1的位置上。
- 2 2 2:因为在这个排列中有 b 2 b_2 b2个整数大于 2 2 2且在 2 2 2之前,又因为这些证书还没有被插入进来,所以必须给这些数留出 b 2 b_2 b2个空位置。因此,把 2 2 2放在第 b 2 + 1 b_2+1 b2+1的空位置上。
- ⋯ ⋯ \cdots \cdots ⋯⋯
- k k k:(一般步骤)因为在这个排列中 k k k前面还应该有 b k b_k bk个整数,这些整数还没有被插进来,因此必须给这些数留出 b k b_k bk个空位置。在本步骤开始时,空位置的个数是 n − ( k − 1 ) = n − k + 1 n-(k-1)=n-k+1 n−(k−1)=n−k+1,把 k k k放在从左边数第 b k + 1 b_k+1 bk+1个空位置上。因为 b k ≤ n − k b_k\le n-k bk≤n−k,所以可以确定一个空位置。
- ⋯ ⋯ \cdots \cdots ⋯⋯
- n n n:把 n n 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]
3 奇排列与偶排列
习惯上,按照某个排列中的逆序个数是偶数还是奇数而把
{
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的符号。
4 交换得到自然顺序
如果排列 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。步骤为:
- 首先连续地把 1 1 1与它左边的 b 1 b_1 b1个整数交换;
- 再连续地把 2 2 2与它左边大于 2 2 2的整数交换;
- ⋯ \cdots ⋯
例子:交换
361245
361245
361245到
123456
123456
123456。
361245
316245
136245
132645
123645
123465
123456
361245\\ 316245\\ 136245\\ 132645\\ 123645\\ 123465\\ 123456
361245316245136245132645123645123465123456
5 参考资料
- 《组合数学》第五版 P57-P60