从5.1的标题COMBINATORIAL PROPERTIES OF PERMUTATIONS来看,这一节应该会涉及比较多的组合数学的东西,这一节也属于比较有意思的一节。
反序和反序对
Inversions 反序,这是什么概念呢?对于排序,当然,排列是重要的研究对象,那么反序应该也是针对排列而言的。
Let (ai a2 ... an) be a permutation(排列) of the set
{1,2,..., n}. If i < j and ai > aj,
the pair (ai,aj) is
called an inversion(反序对) of the permutation;
从该定义来看,反序对就是违背了排序的一对元素,唯一没有反序对的排列就(1,2,...,n)。
事实上,在学线性代数的时候,求n*n行列式的时候,我们曾经用过反序的概念,G. Cramer 在1950提出的公式
上面的求和是对(1,2,...,n)的所有排列求和,而inv(a1a2...an) 是该排列的反序对个数,我们简单叫做反序数。
反序表和反序数
The inversion table(反序表) b1b2
... bn of the permutation a1 a2 ... an
is obtained by
letting bj be the number of elements to the left of j that are
greater than j. (bj等于大于j且在j右边的元素个数的总和)
In other words, bj is the number of inversions whose second
component is j.
例子:591826473 的反序表为 2 3 6 4 0 2 2 10,
since 5 and 9 are to the left of 1; 5, 9, 8 are to the left of 2; etc.
当然从这个定义看出反序表主要是对自然数的排列进行定义的。这也可以扩展,但是讨论问题而言就变得简单了。大多数也需要对一个排列的序号进行研究。
那么反序表的所有元素加起来就是排列的反序数了。而且反序表满足0 <= b1 <= n - 1, 0<=b2<=n-2,
..., 0 <= bn-i <= 1, bn = 0.
反序表和其排列有着一一对应的关系,
从排列到反序表,我们已经知道是唯一的,那么如何从反序表到排列呢,只要我们先把最大值写下,然后从大到小通过插值的方法就可以完成其排列了,因为bn一定为0,这样就可以唯一确定一个排列,这个性质很重要,对解决问题的转化也很有帮助。
例如计算排列个数时,我们以前常用的是一种策略,选第一个有n种,选第二个有n-1,所以是n的阶乘,那么从数学来看,反序表更直接,因为反序表的每个元素是独立的,算出来也是n的阶乘。
另一个例子,在第一卷的1.2.10中,曾经计算过排列的局部最大值的问题,就是计算有多少个元素大于他们所有的后继的问题。那么这个数就是反序表中所有有反序极大值的元素的个数总和,这个极大值指的是bj=n-j的时候。这是因为,当bj=n-j时,那么说明大于j的数全部在j的左边,那么右边的数一定是小于j的,所以该数也是具有局部最大值的。那么当我们求一个排列的平均局部最大值个数的时候,用反序表可以简单解决这个问题,因为反序表每个元素都是独立的,所以,b1有1/n概率是n-1,类似的,可以得到,该平均值是1/n+1/(n-1)+..+1=Hn。
在原排列中随意交换两个相邻元素,反序数总是加一或者减一,这个也很容易证明,因为只对相邻的那两个元素的反序对有影响,要不就是从反序对变成不是反序对,要不就是从不是反序对变成反序对。对其他元素并没有影响。
文中还给出了阿基米德的均匀多面体的图,加深直观理解,也颇有趣味。越来越兴奋的发现在下面展示。
排列的逆和反序表
一个排列的逆和该排列有着相同的反序数。Rotha给出了比较有趣的证明。
We construct an n x n chessboard having a dot in column j of row i whenever ai = j. Then we put × 's in all squares that have dots lying both below (in the same column) and to their right (in the same row).
下面是591826473的构造图:
文中说容易看出构造图中的× 的个数就是反序数。这里我们可以知道,在黑点左边的格子数就是该元素的比它小的元素的总数。而除去一些在它前面,又比它小,就可以得到在它后面,又比它小的数,这个数就就构成数对反序对,所有的× 的个数也就是反序对的总和,即反序数。
那么我们现在把图转置一下,交换行列,(相当于把图按照图的y轴向面向你的方向转180°,然后把得到的图再按图的中心旋转90°),那么得到的就是该排列的逆的图了。经过转置,图中的× 的个数是不变的,所以就可以得到证明。
已经讨论了反序的一些基本概念和有趣的对应关系,有人会思考这和排序有什么关系,肤浅地看,排序就是把有高反序的排列变成0反序的,还记得那个多面体么。从一个点到顶端。这似乎有着比较有趣的关系。
反序数
![](http://hi.csdn.net/attachment/201109/5/0_1315208476ZUJ8.gif)
![](http://hi.csdn.net/attachment/201109/5/0_1315211424cyVZ.gif)
这个证明也比较容易,我们知道每个元素的反序数是独立的,那么把原排列从最右边反排到最左边,得到一个新的排列,就某个元素来说,其反序数应该是原排列该元素的反序数极大值与其反序数之差,所以所有元素加起来,则新排列的反序数应该是反序数极大值与原排列的反序数之差,由于各元素是独立的,那么反序数极大值就是各个元素反序数极大值之和,即0+1+...+(n-1)=n(n-1)/2,即所求。所以每一个排列都可以找到另一个排列与其有对应(可能是本身),所以就有对称性质,并且有上述公式。
我们令生成函数为Gn(z) =
In(0) + In(l)z + In(2)z2 + .......,该生成函数满足Gn(z) =(1+z+z2+...+zn-1)
Gn-1(z);
这个满足递归关系正文也说不难看出,看来我愚钝了,要看很久才看出。
首先,每一个n-1个元素的排列,添加一个元素都将都成n个新的排列,排列的总个数也是原来的n倍,那么这么多新的排列会对反序数造成什么影响呢,反序数的最大值也将从(n-1)(n-2)/2增大到n(n-1)/2,而对于In-1(0)来说,由于第n个元素是独立于其他元素的,所以,原排列中反序数为0的排列将产生反序数为0,1,.....,n-1,原排列中反序数为1的排列将产生反序数为1,2,.....,n以此类推,就可以知道那递归关系是满足的。
再进行深度递归,分子分母相乘(1-z)n化简,得出式子:
![](http://hi.csdn.net/attachment/201109/6/0_1315285971SQ0g.gif)
![](http://hi.csdn.net/attachment/201109/6/0_1315286276ZN7h.gif)
从前面的分析,我们知道,每一个原排列反序数小于等于k的都将为新排列反序数为k的做一次贡献,那么In(k)=In-1(k)+In-1(k-1)+.....+In-1(0)对于k<n,将此式子的k换成k-1,照样成立,那么In(k-1)=In-1(k-1)+In-1(k-2)+...+In-1(0),代换,那么上面的式子得证。
到这里,我们是不是想起了杨辉三角。这里并不想说杨辉三角和这里有什么关系,但是杨辉三角和组合数的一些性质有关,和多项式系数也有关,这里面和反序数到底有没有本质上的联系?这应该留待我们去发掘和讨论。
那么对于n和k,可以不可以马上计算出In(k)的值呢?答案是肯定的。
![](http://hi.csdn.net/attachment/201109/6/0_13152885463xkf.gif)
n = p1 + p2 + ...+ Pk,
where p1> P2 > .....> Pk > 0. For
example, the partitions of 7 into distinct parts are 7, 6 + 1, 5 + 2, 4 +
3, 4 + 2 + 1。
Let fk(n) be the number
of partitions of n into k distinct parts; prove that ∑k (-1)k
fk(n) =0, unless n has the form (3j2 ± j)/2, for
some nonnegative integer j; in the latter case the sum is (-1)j.
这一题说一个数n可以分划成k个正整数之和,然后令fk(n)是n可以分成k部分的不同分法次数,要证明这些∑k(-1)k fk(n) =0,当存某个整数j,令u=(3j2 ± j)/2,∑k(-1)kfk(n) = (-1)j 。
![](http://hi.csdn.net/attachment/201109/6/0_13152968147pN9.gif)
我们让n的其中一个划分,从p1到pk往下排,第一行画p1个黑点,第二画p2个黑点,以此类推,我们就得到类似左边的图。
然后我们把满足pj+1<pj - 1的最少j,把头j行的最后一个黑点圈起来,如图,如果j(即圈起来黑点数)小于pk(最后一行的黑点数),那么把圈起来的j个点放在最下面,成为新的一行,如右边的图。类似的,如果是j大于等于pk,就可以把pk那一行转45°放在圈起来黑点的右边,成为另一个图。
这样的转化,我们可以知道,每一个偶行加法划分都存在着对应的奇行加法划分,除非某个划分是没办法找到对应的。
假设j<k,则无论j和pk是什么关系,都可以有对应。当j=k时,j只有在等于pk和pk-1时没办法(注意这里的p1>p2>...>pk)
这样就意味只有当j=k=pk或者j=k=pk-1才没有对应
故此有j行,每行相差1,pk是j或者j-1,可以得到n=(2j-1)+..+j=(3j2-j)/2和n=2j+..+(j-1)=(3j2+j)/2 。
那么没有对应的项,就会使∑k (-1)k
fk(n)!=0,而是∑k(-1)kfk(n)=(-1)j
(k=j ,fk(n)=1)。
![](http://hi.csdn.net/attachment/201109/6/0_1315302234h665.gif)
讲完了反序数的个数,接下来的正文又令我大为吃惊,涉及到反序分布的问题。
反序分布
首先,讲我们前面讲到过的In(k)序列的生成函数Gn(z)除以n!,那么我们得到gn(z)=h1(z)h2(z)....hn(z),其中hk(z)=(1+z1+...+zk-1)/k。
从hk(z)可以看出这个生成函数是关于小于k的随机非负整数的一致分布。因为小于k的非负整数概率都是1/k。然后我们就可以知道这些小的生成函数相乘,概率相乘,h1(z)相当于第n个元素反序数的一致分布,h2(z)是第n-1个函数,hn(z)是第1个元素,它们相乘这就构成了n个元素的随机排列的反序数概率分布生成函数!
这里的平均数和标准差比较容易计算,这里用了一致分布求平均值和标准差的推导公式,(缺,回宿舍找),再利用平方和公式也很容易计算出来了。有兴趣的同学可以验证下。
反序分布无疑是比较有趣的,我们根本不晓得反序原来也有概率的,我们在排序之前得到的序列也是随机的,那么利用概率学来计算排序的平均快慢也是比较有益的。
排列的反序与指数
说起指数,很多人都会想起数学里面的指数,但是这里说的是index,翻译成指数也不是很妥当,但是我们只要知道排列中的这么一个概念就好了。
Let us define the index of the permutation a1a2 ... an as the sum of all subscripts j such that aj>aj+1, 1 <= j < n. For example, the index of 591826473 is 2 + 4 + 6 + 8 = 20.
这个定义是找到相邻的两个数,如果左边大于右边,就把左右的下标记录下来,把这些下标想加,就是这个排列的指数。
如果列出n个元素的排列,我们会发现指数和反序个数相同,我们还可以看到有多少个指数是k个的排列,就有多少个反序数为k的排列。如果有列出来,这个对应看起来是显然的,但是证明却是非常有趣的。
首先我们假设ind(a1a2...an)是某个排列的指数,并且用Hn(z)=∑ zind(a1a2...an)表示对所有排列指数的生成函数。那么我们要求的目的就是让Gn(z)=Hn(z),只要生成函数一样,那么各个系数一样,那么就说明有多少个指数是k个的排列,就有多少个反序数为k的排列,也即是In(k)。
为此,我们定义每个元素都是非负整数的任意n元组(q1,q2,…,qn)为一边,然后定义((a1a2…an),(p1p2..pn))为另一边,其中a1a2…an是一个排列,而p1>=p2>=..>=pn>=0。
这个对应假设能满足q1+q2+…+qn=ind(a1a2...an)+p1+p2+...+pn 。
我们先假设可以找到这个对应来证明Gn(z)=Hn(z)。
再设Qn(z)是对非负整数的任意n元组(q1,q2,…,qn)求和的生成函数,即Qn(z)=∑ zq1+q2+…+qn=1/(1-z)n
Qn(z)怎么求出来,回忆起第一卷讲生成函数里面,有一条简单但是很重要的公式,1/(1-z) = 1+z1+z2+….,那么我们把n个(1+z1+z2+….)相乘,根据组合选取的思路,我们肯定该结果就是所求Qn(z)。注意这里的(q1,q2,…,qn)是任意非负整数的组合。
又设Pn(z)是对满足p1>=p2>=..>=pn>=0的整数的任意n元组(p1p2,…,pn)求和的生成函数,即Pn(z)=∑ zp1+p2+…+pn=1/(1-z)(1-z2)(1-z3)…(1-zn)
Pn(z)又是怎么求出来的呢?作者有叫我们去看习题15,这里插点讲这个的证明。
首先我们知道Pn(z)的某个zm的系数就是m可以分成p1+p2+…+pn的分划的个数,习题中的说法就是至多分成n个部分的分划生成函数。这里的至多,意思是某些项可以为0,而0项是不计算入分划的部分数的。
该习题试想证明一个简单的定理,至多分成n个部分的分划和分成每个项不超过n的分划是对应的,有着相同的数量。其实定理的证明很简单,我们先把m的一个分划,该分划是由至多n项组成的,然后把这个分划按照富兰克林对应的点阵图画出来,然后把改图转置,即行列对换,我们即可以得到一个m的分划,该分划每一项都不超过n。按照同样的做法,我们也可以反过来执行这个过程,注意虽然有些点阵图既是至多分成n个部分的分划,又是分成每个项不超过n的分划,但是这都不会影响它们有相同数量的结论。
有了上面的定理,我们就可以把求Pn(z)的某个zm的系数变成求m可以分成每个项不超过n的分划的个数了。问题转化了。
因为项数不确定,但是不超过n的数是确定的,即是0到n,那么可以选择0无数个,选择1无数个,...,选择n无数个,它们之间是独立的。那么
Pn(z) = (z0(0)+z0(1)+z0(2)+…)(z1(0)+z1(1)+z1(2)+…)(z2(0)+z2(1)+z2(2)+…)…(zn(0)+zn(1)+zn(2)+…)1/(1-z)(1-z2)(1-z3)…(1-zn)
上面的式子很容易计算,(z1(0)+z1(1)+z1(2)+…)就是1+z1+z2+….=1/(1-z) ,(z2(0)+z2(1)+z2(2)+…)用z2乘于该式再减该式就可以求出来,其它类似。
至此,两个式子得证。
那么根据q1+q2+…+qn=ind(a1a2...an)+p1+p2+...+pn,我们马上能够得到Qn(z)=Hn(z)Pn(z),所以Hn(z) = Qn(z)/Pn(z) = (1-z)(1-z2)(1-z3)…(1-zn)/(1-z)n=Gn(z),式子中的n指得就是排列中元素数。
到此,我们已经证明了我们的目的,但是证明完整么?不,还差一个重要假设没验证,就是能够找到满足q1+q2+…+qn=ind(a1a2...an)+p1+p2+...+pn 的对应。
该对应很有趣,首先我们考虑(p1p2,…,pn)是递减的,那么我们要把(q1,q2,…,qn)按照递减稳定排序,那么qa1>=qa2>=…>=qan,并且当qaj=qaj+1时aj<aj+1。
那么,我们把n元组(qa1,qa2,…,qan)进行如下的操作,取j从1到n遍历一下操作,当某aj>aj+1,把新元组中qa1到qaj都减去1。
由于qaj>=qaj+1,但是qaj不可能等于qaj+1,因为aj>aj+1和之前的说法违背。
所以我们得到qaj>qaj+1,故此,我们把新元组进行一次操作之后它还是能够满足稳定递减的要求,所以进行n次之后还是得到一个稳定递减的全新元组。
这个全新的元组就是我们要求的(p1p2,…,pn),那么我们在操作之中,我们是当aj>aj+1时我们就把qa1到qaj减去1,刚好减去j,从这里可以看出正好满足排列的index指数的定义。
(注意这里你可能要以为j从1到n遍历是一个必须的顺序,其实不然,因为这个减数是由(a1a2...an)决定,也就是排序完之后就决定的,所以和这个顺序是没关系的,而且你也可以知道每一次操作都是qaj>qaj+1,所以只会使qaj=qaj+1,而下一次选择j的时候可能大于j,那么比较的有可能是qaj+1和qaj+2,由于之前的操作对qaj+1没影响,所以并不影响结果,再者如果下次选择的是小于j的,那么由于之前大于aj的元素都必须减1,所以还是稳定的,所以该被选择的还是会被选择到。)(遍历的顺序)
所以q1+q2+…+qn=ind(a1a2...an)+p1+p2+...+pn,相反的,从ind(a1a2...an)+p1+p2+...+pn对应到q1+q2+…+qn,也比较容易找到了。这里不再详细解说。到此我们找到该对应。
所以前面提到的有多少个指数是k个的排列,就有多少个反序数为k的排列的定理得到证明。
后面作者还给出了这个定理更广泛的定理,有着k个反序和l个指数的n个元素的排列的数目,和有l个反序和k个指数的排列数目相同。
还扯到两个伟大人物和第一排列和第二排列的对应。至此作者给出了习题25。
关于反序的研究,正文就这样结束了,从后面的指数部分我们可以看出一点和排序的眉目出来,反序作为研究排序的效率应该是很有帮助的,而且从证明来看,作者不断使用转换问题的思路,给我们解决问题留下深刻的体验。
关于正文里面还是更多细节可能没有去证明或者严谨,有兴趣的同学可以自觉完善。下面附带研究下习题25。
习题25:
这一题主要是对上面说的反序和指数的关系问题,进一步研究,把上面的命题缩小,得出更为吃惊的结论。
结论就是:有着k个反序和l个指数的n个元素的排列的数目,和有l个反序和k个指数的排列数目相同。
但是习题并没有一下要求我们证明那么多,而是分成两步:
我们先假设排列为A=a1a2…an,inv(A)表示A的反序数,ind(A)表示A的指数。为了简单,我们假设对于1到n进行排列。
第一证明:
每一个排列A都有另一个排列f(A)与之一一对应,关系如下:ind(f(A)) = inv(A),并且对于1<=j<n,每当在A中j在j+1的左边,在f(A)中j也在j+1的左边,反之,也成立。
第一个证明作者给了提示,构造如下的h关系:如果n>1,A可以写成A=x1A1x2A2…xkAkan,其中当a1<an时,x1,x2,…,xk时都是小于an的元素,反之,x1,x2,…xk时都是大于an的元素,而其它元素出现在子排列A1,A2,…,Ak中,注意这里的子排列可能为空。
这个构造咋一看起来很复杂,读者可以自己构造例子,很容易就接受了。但是这个构造有什么用呢?可以用来证明第一个证明么?
事实上,我们还需要构造h(A)=A1x1A2x2…Akxk,构造这个h的关系,是巧妙地用了反序和指数共同特点,前后大小关系的反转。
稍微分析下,当a1<an时,A和h(A)的反序数是相同的,这是因为x1,x2,…,xk都是小于an的元素,所以xj的反转对于an没有影响,所以而对于Aj的反转,相对an来说反序数是减少了,但是由于xj的反转相对Aj来说反序数是增加,而且很容易知道是减少的是所有Aj子排列中元素的个数,而增加的也刚好是是所有Aj子排列中元素的个数,所以反序数不变。
当a1>an时,A到h(A)的反序数是减少了n-1,这是因为,x1,x2,…xk时都是大于an的元素,没了an,所有xj反序数减一,而Aj则不会受影响,但是由于由于xj的反转相对Aj来说,反序数是减少的,减少的是所有Aj子排列元素的个数,两个减少的部分加起来刚好就是整个h(A)元素个数之和,刚好是n-1。
看到这里,虽然还是模糊不明,但是从n-1我们可以看出指数的倪端。
这时我们只要用一个递归来弄,让f(A)=f(h(A))an,注意:这里的an指的是f映射x集合里面的最后一个元素,也就是排列的最后一个元素,所以这是递归的关系。这个f(A)也就是我们第一个证明所求的。
首先,从f(A)=f(h(A))an,可以知道,我们一直让A往下递归将可以得到一个排列,而且每轮递归得到的结果的反序数都会等于前面一轮中h(A)排列的反序数或者是其减去一个数,这个数就是该结果元素个数减1,这个结论是从前面的分析得到的,那么,在什么时候才会减一,什么时候才是相等呢?答案很明显,就是a1>an,但这并不能解决问题,因为计算指数是必须相邻两个数的关系,再次仔细看看反转过程,我们会发现,假如现在a1>an,那么我们这一轮得到的h排列中,最后一个元素是xk,这个元素是必须大于an的,而最后一个元素又是作为下一轮的an来输出,所以下一轮的那个an一定是f(A)中存在指数的一个元素,所以指数必然会加上其下标,而这个下标刚好是这一轮的n-1。那么当a1>an时,就意味着有一个指数值产生,而这个值刚好是反序数减少的值,那么一直递归下去,A反序数最终会是0,而f(A)指数值则增加到A的反序数。所以第一条件得证。
再者,从递归的过程来看,对于某一轮来说,对于1<=j<n,每当在A中j在j+1的左边,那么当前的an,要么大于j和j+1,那么小于j和j+1,那么它们大多数轮有相同的反转行为,只有当j+1作为an的时候输出才会有不同,但是j+1总是先于j输出,所以在f(A)中j也在j+1的左边。到此,第二条件得证。
至此,我们已经证明了第一个证明。这过程看起来繁琐,但是该证明巧妙用了递归和转化,利用指数和反序数的共同点,进行反转,特别有趣。通过构造我们也可以很容易计算出一个排列的f(A)和计算它的反过程f-1(A)。这个碍于篇幅,大家可以自己试着完成。过程是完全可以反过来的,因为a1和an同时会存在。
第二证明:由前面的f关系证明有另一种关系g满足ind(g(A))=inv(A)和inv(g(A))=ind(A)。
这个证明的关键是要证明两个等式,设A-是A的逆,那么inv(A)=inv(A-)以及ind(A-)=ind(f(A)-)。第一条等式我们前面已经采用点X图证明过了(忘记了?砍看回前面吧!)。
第二条式子证明如下:我们知道假设1<=j<n,每当在A中j在j+1的左边,那么该A的逆,会有产生一个相邻的元素对(bj,bj+1),并且bj<bj+1,这是因为排列逆的定义以及j在j+1的左边导致的,这就说明A逆的指数可由A来看出,假设,原排列是198263745,那么在该排列的逆中,满足前面条件的是12345,67,8,9。所以我们可以知道在在逆146895732中,第五、七、八位是有指数存在的,由于第九位是最后一位,不算。那么f(A)呢,由于第一个证明,我们知道,f(A)和A在前面提到的条件中存在一致关系,所以,在f(A)逆中存在指数的位应该和A是一摸一样的,所以很容易证明第二条式子成立,即ind(A-)=ind(f(A)-)。
前面两条式子成立后,我们再定义如下式子,A1 = A-, A2 = f(A1), A3 = A2-, A4 = f-1(A3), A5 = A4- ,我们就可以得到下面两条证明:
inv(A5)
= inv(A4) = ind(A3) = ind(A2-) =
ind(A1-) = ind(A);
ind(A5) = ind(A4-) = ind(A3-) = ind(A2) = inv(A1) = inv(A);
注意A4 = f-1(A3),A3=f(A4)是一样的 。
上面的等式都是替换,很容易计算,读者自行证明。到此,第二个证明已经结束了,从后面的等式可以看出g的关系还是比较复杂的,先逆后求f再逆求f-1再逆,才求出g来。
一个排列通过一系列变化就可以找到反序数和指数互换的排列来,这是一件很奇妙的对应,以致我们常常想有没有找到一个跟自己一样的呢?这个应该不太可能,哈哈。
这一节到这里就结束了,还有很多习题可以研究,这里就不再深入。