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 : 2 : 1 : \begin{aligned} &8:8\\ &7:87\\ &6:867\\ &5:8657\\ &4:48657\\ &3:\\ &2:\\ &1: \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到 123456。
\\ \\ \\ \\ \\ \\ 361245316245136245132645123645123465123456
5 参考资料
- 《组合数学》第五版 P57-P60
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/87118.html