关于生成排列
2013-06-24 20:41
211 查看
写数学笔记是源于我对matrix67的崇拜,从高二开始关注m大的博客,每次读到那种巧妙的思维,我都想跳起来大喊大叫:简直是太nice了。我喜欢数学,最喜欢的地方就是这里,这和从小老师说的苦思冥想做出一道数学题的感觉一样。哦不,是更加令人震撼!说实话吧,我也不知道我能坚持多久,虽然我的目标是写到大学毕业再说。认识我的人都知道我这人最大的特点就是没耐心。不过既然我喜欢摸索这种思维的巧妙,我就应该能坚持下去。我把自己的数学笔记公布出来,一是方便自己整理,二是给我的朋友中的geek们提供一个平台,来和我分享这些nice的思想。当我在写第一篇笔记的时候,我还是不懂使用一些专业的数学软件来表达我的思想,我会在近期完成这些软件的学习。当然,如果有一些不专业的毛病也请各位朋友指出,我也是在不断学习中进步。好了,废话到此为止,以下是正文。
这是我在读richard A. brualdi的《introductory combinatorics》第四章发现的好东西。一瞬间让我觉得之前我的排序优化简直弱爆了。在这篇笔记里,我会着重和大家介绍如何从逆序列到生成排列的过程。
关于排列大家都明白,但是如何生成一个排列一直是在排序算法中困扰我们的。比如一个由n个正整数构成的集合{1,2,3,……,n}就有n!个排列,就算n为15,n!就比1
000 000 000 000还要大。这里我贴出stirling公式:http://baike.baidu.com/view/2019233.htm用来吓吓大家。
当然,书中介绍了好几个方法来生成排列,而我觉得一直到S.Even的方法都还算得上比较原始。一直引出了逆序列这个概念,从而推出了两个相当精彩的排列生成。我也尝试搜索了一下逆序列的资料,起码百度的前几页没有看到。那么我先简单介绍一下逆序列:逆序是一个老概念,我不多说。对于一个排列i1,i2,i3……in,我们令aj表示第二个成分是j的逆序的数量。通俗的说,aj等于排列中在j前面又大于j的数的个数,用来度量j的无序程度。
数值序列:
a1,a2,……,an
叫做排列i1.i2,……,in的逆序列。当然他们的和就是用来度量原数列无序程度的逆序数。
好了,到此为止可以切入正题了,逆序列的性质就暗示了我它的作用。假设数列{b1,b2……,bn}是一组数列的逆序列,那么必然0≤b1≤n-1,0≤b2≤n-2,……,0≤b(n-1)≤1,bn=0.很明显,整数序列{bn}的序列个数正式n*(n-1)*……*2*1=n!。好了,这就自然而然的想到了,原数列所有的排列正是n!,那么和逆序列是不是有着一一对应的情况呢?答案是肯定的,证明方法也就是我接下来说的算法。
先确定一个数列,为了方便我就引用了书中的例子{1,2,3,4,5,6,7,8},使其逆序列为5,3,4,0,2,1,1,0.
算法一:
首先确定n,然后确定n-1,n-1的位置就是根据b(n-1)来确定的,如果b(n-1)为1,那么原序列为{n,n-1},如果b(n-1)为0,那么原序列为{n-1,n}。显然在这一步,b(n-1)只有两个情况。我们来考虑下一般步骤,在确定n-k这一步时,前面步骤的n到n-k+1的顺序已经确定,而n-k一定是比之前确定的任意一个数还要小,也就是n-k所对应的逆序就能找到它所在的位置。我拿例子模拟一遍。
8:8
7:87
6:867
5:8657
4:48657
3:486537
2:4862537
1:48625137
因此排列就出来了,当然算法一虽然能够实现还原原排列,但是之前所确定的数,它的位置不是绝对固定,而是相对的。在用计算机模拟的时候,会造成一个不必要的位移过程。J.csima向作者推荐了另外一个算法。
算法二:
和之前的不同,我们先确定原数列1的位置,因为1之前有b1个整数,(除了0,1任何一个整数都大于1不是吗?)所以1是放在b1+1的空位置上。那么2就放在第b2+1个空位置上。而一般来说,当我们要确定k的时候,就需要把k放在第bk+1个空位置上,因为k后面要放的数必然大于k,插入在k前面就会形成逆序。可能文字表达有点吃力,毕竟我这是第一篇数学笔记,不能理解的同学就看我下面的举例,依旧是拿上面的数列。
这个算法的好处就是,每一个要确定的数,它的位置是绝对固定的。在程序中实现的话,我们就能避免那个很烦人的位移数字的过程。
当然,以上两种排列的生成方法都证明了逆序列是和原数列的排列一一对应的。只要我们指定一个排列的逆序列就可以唯一确定这个排列。
我在高中的时候就接触了逆序数,可是限制于当时的代数知识匮乏,我没有搞清楚逆序数的原理。这次碰上了,就没有再放过它。《introductory combinatorics》中还有部分关于逆序数的讨论,我就不再提出来继续唠叨,《高等代数》北大版中也有详细的关于逆序数的讨论,有兴趣的朋友可以尝试去看看。
这是我在读richard A. brualdi的《introductory combinatorics》第四章发现的好东西。一瞬间让我觉得之前我的排序优化简直弱爆了。在这篇笔记里,我会着重和大家介绍如何从逆序列到生成排列的过程。
关于排列大家都明白,但是如何生成一个排列一直是在排序算法中困扰我们的。比如一个由n个正整数构成的集合{1,2,3,……,n}就有n!个排列,就算n为15,n!就比1
000 000 000 000还要大。这里我贴出stirling公式:http://baike.baidu.com/view/2019233.htm用来吓吓大家。
当然,书中介绍了好几个方法来生成排列,而我觉得一直到S.Even的方法都还算得上比较原始。一直引出了逆序列这个概念,从而推出了两个相当精彩的排列生成。我也尝试搜索了一下逆序列的资料,起码百度的前几页没有看到。那么我先简单介绍一下逆序列:逆序是一个老概念,我不多说。对于一个排列i1,i2,i3……in,我们令aj表示第二个成分是j的逆序的数量。通俗的说,aj等于排列中在j前面又大于j的数的个数,用来度量j的无序程度。
数值序列:
a1,a2,……,an
叫做排列i1.i2,……,in的逆序列。当然他们的和就是用来度量原数列无序程度的逆序数。
好了,到此为止可以切入正题了,逆序列的性质就暗示了我它的作用。假设数列{b1,b2……,bn}是一组数列的逆序列,那么必然0≤b1≤n-1,0≤b2≤n-2,……,0≤b(n-1)≤1,bn=0.很明显,整数序列{bn}的序列个数正式n*(n-1)*……*2*1=n!。好了,这就自然而然的想到了,原数列所有的排列正是n!,那么和逆序列是不是有着一一对应的情况呢?答案是肯定的,证明方法也就是我接下来说的算法。
先确定一个数列,为了方便我就引用了书中的例子{1,2,3,4,5,6,7,8},使其逆序列为5,3,4,0,2,1,1,0.
算法一:
首先确定n,然后确定n-1,n-1的位置就是根据b(n-1)来确定的,如果b(n-1)为1,那么原序列为{n,n-1},如果b(n-1)为0,那么原序列为{n-1,n}。显然在这一步,b(n-1)只有两个情况。我们来考虑下一般步骤,在确定n-k这一步时,前面步骤的n到n-k+1的顺序已经确定,而n-k一定是比之前确定的任意一个数还要小,也就是n-k所对应的逆序就能找到它所在的位置。我拿例子模拟一遍。
8:8
7:87
6:867
5:8657
4:48657
3:486537
2:4862537
1:48625137
因此排列就出来了,当然算法一虽然能够实现还原原排列,但是之前所确定的数,它的位置不是绝对固定,而是相对的。在用计算机模拟的时候,会造成一个不必要的位移过程。J.csima向作者推荐了另外一个算法。
算法二:
和之前的不同,我们先确定原数列1的位置,因为1之前有b1个整数,(除了0,1任何一个整数都大于1不是吗?)所以1是放在b1+1的空位置上。那么2就放在第b2+1个空位置上。而一般来说,当我们要确定k的时候,就需要把k放在第bk+1个空位置上,因为k后面要放的数必然大于k,插入在k前面就会形成逆序。可能文字表达有点吃力,毕竟我这是第一篇数学笔记,不能理解的同学就看我下面的举例,依旧是拿上面的数列。
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 |
| (1) | (2) | (3) | (4) | (5) | (6) | (7) | (8) |
这个算法的好处就是,每一个要确定的数,它的位置是绝对固定的。在程序中实现的话,我们就能避免那个很烦人的位移数字的过程。
当然,以上两种排列的生成方法都证明了逆序列是和原数列的排列一一对应的。只要我们指定一个排列的逆序列就可以唯一确定这个排列。
我在高中的时候就接触了逆序数,可是限制于当时的代数知识匮乏,我没有搞清楚逆序数的原理。这次碰上了,就没有再放过它。《introductory combinatorics》中还有部分关于逆序数的讨论,我就不再提出来继续唠叨,《高等代数》北大版中也有详细的关于逆序数的讨论,有兴趣的朋友可以尝试去看看。
相关文章推荐
- 生成1~n的全排列
- 关于Py2exe生成文件找不到egg安装模块解决办法
- Hibernate 中关于主键生成策略之联合主键
- 关于自动生成数据库的说明文档
- 关于android文件布局在R类不能生成
- Tensorflow中关于随机数生成种子tf.set_random_seed()
- 关于在windows,利用java语言,phantomJS,highcharts实现服务器端自动生成图表
- 关于如何使用SqlServer中@@Identity、@@IDENT_CURRENT、@@SCOPE_Identity获取自动生成列的值的区别(精简版)
- (排列生成算法)枚举排列的两种方法:递归枚举和next_permutation (使用多用next_permutation)
- 生成可重复的排列(递归)
- 关于求排列组合数
- 关于dll文件的生成以及找不到jni.h的解决办法(fatal error C1083: Cannot open include file: 'jni.h':)
- UVa 10098 快速生成有序排列
- 关于Spring中配置LocalSessionFactoryBean来生成SessionFactory
- 减治法在生成全排列中的应用(JAVA)--回溯、Johnson-Trotter算法、自字典序
- .net关于企业Excel报表的生成 (转)
- 随时点滴--------关于项目设置中的“生成后事件”设置
- 怎么把我生成的Textbox排列成3列
- Johnson-Trotter(JT)算法生成排列
- 关于算法竞赛入门经典一书的思考学习——枚举排序和子集生成!