有重复元素的全排列
各种排列组合问题的统一处理

n1 + n2 + …+ nm = n
从 n 个相异的元素中取出允许重复使用的 r 个元 素 , 不管怎样的次序并成一组 , 叫做 n 个相异元素 的允许重复的 r 元组合 , 简称重集的 r2 组合 [ 2 ] .
∑
n! n n n x 11 x 22 …x mm . n1 !n2 ! …nm !
0 引言
排列与组合是组合数学中的两个重要的概 念 ,是一类重要的基本计数方法 . 可重复排列与可 重复组合在理论和实际中的应用更为广泛 . 本文 试图以可重复全排列的基本思想来统一解决所有 的排列组合问题 , 从而得出排列与组合的可以相 互转化的结论 . 首先给出一个本文中要多次使用的可重复排 列公式[ 1 ] 以及可重复组合的概念 . 设 S = { k1 a1 , k2 a2 , …, k n a n } 是 n 个不同元素 的多重集 , 其中第 i 个元素的重数为 k i , 令元素的 总数 k = k1 + k2 + … + k n , 则 S 的所有元素的不 同 k 2重复排列数为
n! n! = = ( n - r) ! 1 !1 ! … 1 ! ( n - r) !
r n ( n - 1) …( n - r + 1) = P n .
数为 ( 4) . 从不同的角度考虑 , 可得到两种不同的证明 方法 . 证明 1 从 n 个盒子中选 n1 个放入 a1 , 每个 盒子中放一个 , 虽然盒子是编号的 , 但每个盒子中
r 一排 , 方案总数自然是 C n .
这又一次证明组合可以看成一种特殊的可重 复排列 .
第3期
排列计算方法范文

排列计算方法范文排列是数学中的一种组合方法,指的是从一组元素中选取出一部分元素进行排列。
排列的计算方法包括全排列和部分排列。
一、全排列全排列是将一组元素的所有可能的排列情况都列举出来。
比如,对于元素集合{1,2,3},全排列的结果为{1,2,3}、{1,3,2}、{2,1,3}、{2,3,1}、{3,1,2}、{3,2,1}。
下面介绍几种计算全排列的方法。
1.递归法递归法是一种常用的计算全排列的方法。
具体步骤如下:(1)选取第一个元素作为排列的开头;(2)将剩下的元素进行全排列;(3)将第一个元素与后面所有元素进行交换,并重复第(2)和第(3)步,直到最后一个元素;(4)输出排列结果。
2.字典序法字典序法是通过字典序的规律来计算全排列的方法。
具体步骤如下:(1)对于给定的一组元素,从右往左找到第一个左边小于右边的元素,记为a[i];(2)在a[i]的右边找到最小的比a[i]大的元素,记为a[j];(3)交换a[i]和a[j],并将a[i]右边的元素按照递增顺序排列;(4)输出排列结果。
二、部分排列部分排列是从一组元素中选取出一部分元素进行排列。
部分排列的计算方法主要有以下几种。
1.当选取的元素个数与原来元素个数相同时,部分排列就等同于全排列,采用全排列的计算方法即可。
2.当选取的元素个数小于原来的元素个数时。
假设一组元素有n个,选取r个进行排列。
计算部分排列的方法可以利用全排列的计算方法。
3.当选取的元素个数大于原来的元素个数时,部分排列的计算方法较为复杂,需要进行组合运算。
假设一组元素有n个,选取r个进行排列。
计算部分排列的方法如下:(1)从n个元素中选取r个元素进行排列,共有P(n,r)个结果;(2)从n个元素中选取r-1个元素进行排列,共有P(n,r-1)个结果;(3)将第(1)步和第(2)步的结果相减,即P(n,r)-P(n,r-1)。
总结:排列是一种组合方法,全排列是将一组元素的所有可能的排列情况进行列举;部分排列是从一组元素中选取出一部分元素进行排列。
有重复元素的全排列数学公式

有重复元素的全排列数学公式
全排列数学公式可以使用来解决充满重复元素的排列问题,它可以帮助我们理解问题更深入,更直观地计算出结果。
在数学表达式中,我们用n! 来表示有n个数字的全排列。
一个具备n个重复的数字的排
列可以用如下的数学公式来描述:
Pn = n! / d1! * d2! *… * dn!
其中,d1,d2,...dn分别是具有n个重复数字的排列中所有不同的元素的出现的次数。
例如,如果我们有一个只包含1,1,2的元素的排列,那么P3 = 3! / 1! * 2! = 6。
从这里我们可以看到,P3数用只有一个1和一个2的元素为3个元素的排列可以有6种可能。
在这里,我们只介绍了具有n个重复元素的全排列的数学公式,实际上,全排列还具有许
多更为复杂的数学模型,它可以用来模拟各种更复杂的排列问题,包括具有不同数量的重
复元素的排列问题。
通过以上讨论,我们可以看到,全排列的数学公式对于解决带有重复元素的排列问题是非
常有用的。
它可以让我们更加清晰,直观地理解不同的排列总数,也可以更好地计算它们。
全排列的生成算法

全排列的生成算法全排列的生成算法就是对于给定的字符集,用有效的方法将所有可能的全排列无重复无遗漏地枚举出来。
任何n 个字符集的排列都可以与1~n的n个数字的排列一一对应,因此在此就以n个数字的排列为例说明排列的生成法。
n个字符的全体排列之间存在一个确定的线性顺序关系。
所有的排列中除最后一个排列外,都有一个后继;除第一个排列外,都有一个前驱。
每个排列的后继都可以从它的前驱经过最少的变化而得到,全排列的生成算法就是从第一个排列开始逐个生成所有的排列的方法。
全排列的生成法通常有以下几种:字典序法递增进位数制法递减进位数制法邻位交换法递归类算法1.字典序法字典序法中,对于数字1、2、3......n的排列,不同排列的先后关系是从左到右逐个比较对应的数字的先后来决定的。
例如对于5个数字的排列12354和12345,排列12345在前,排列12354在后。
按照这样的规定,5个数字的所有的排列中最前面的是12345,最后面的是54321。
字典序算法如下:设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即j=max{i|pi<pi+1}2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)3)对换pi,pk4)再将pj+1......pk-1pkpk+1pn倒转得到排列p’’=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个下一个排列。
例如839647521是数字1~9的一个排列。
从它生成下一个排列的步骤如下:自右至左找出排列中第一个比右边数字小的数字4 839647521在该数字后的数字中找出比4大的数中最小的一个5 839647521将5与4交换 839657421将7421倒转 839651247所以839647521的下一个排列是839651247。
CSP(NOIP)复习资料——数学知识

设完成一件事有m个步骤,第一个步骤有 种方法,第二个步骤有 种方法,…,第m个步骤有 种方法。必须通过每一步骤,才算完成这件事,则完成这件事共有 种不同的方法。
例1:若一个男人有三顶帽子和两件背心,问他可以有多少种打扮?可以有 种打扮。
例2:从甲地到乙地有2条路,从乙地到丙地有3条路,从丙地到丁地也有2条路。问:从甲地经乙、丙两地到丁地,共有多少种不同的走法?
例2:5个男生3个女生排成一排,3个女生要排在一起,有多少种不同的排法?
解:因为女生要排在一起,所以可以将3个女生看成是一个人,与5个男生作全排列,有 种排法,其中女生内部也有 种排法,根据乘法原理,共有 种不同的排法。
结论2捆绑法:要求某几个元素必须排在一起的问题,可以用捆绑法来解决问题.即将需要相邻的元素合并为一个元素,再与其它元素一起作排列,同时要注意合并元素内部也可以作排列。
3&50 0 0 0 0 0Байду номын сангаас0 1
使用按位与运算可将一个数中的某些指定位清零如:
a: 0 0 1 0 1 1 0 0 1 0 1 0 1 1 0 0
b: 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 (377)8
a &b 0 0 0 0 0 0 0 0 1 0 1 0 1 1 0 0
A. (¬ A∧B)∨(C∧D∨A) B. ¬ (((A∧B)∨C)∧D)
C. A∧(B∨C∨D)∨D D. (A∧(D∨C))∧B
4. C++中的位运算
位运算就是指对数据进行二进制位的运算。位运算的操作数,只能是整型或字符型数据,不能为实型数据。
C++提供的位运算有:
名称
运算符
高中数学 排列组合

高中数学第十章-排列组合二项定理考试内容:分类计数原理与分步计数原理. 排列.排列数公式.组合.组合数公式.组合数的两个性质. 二项式定理.二项展开式的性质.考试要求:(1)掌握分类计数原理与分步计数原理,并能用它们分析和解决一些简单的应用问题. (2)理解排列的意义,掌握排列数计算公式,并能用它解决一些简单的应用问题. (3)理解组合的意义,掌握组合数计算公式和组合数的性质,并能用它们解决一些简单的应用问题.(4)掌握二项式定理和二项展开式的性质,并能用它们计算和证明一些简单的问题.§10. 排列组合二项定理 知识要点一、两个原理.1. 乘法原理、加法原理.2. 可.以有..重复..元素..的排列. 从m 个不同元素中,每次取出n 个元素,元素可以重复出现,按照一定的顺序排成一排,那么第一、第二……第n 位上选取元素的方法都是m 个,所以从m 个不同元素中,每次取出n 个元素可重复排列数m·m·… m = m n.. 例如:n 件物品放入m 个抽屉中,不限放法,共有多少种不同放法? (解:n m 种) 二、排列. 1. ⑪对排列定义的理解.定义:从n 个不同的元素中任取m(m ≤n )个元素,按照一定顺序......排成一列,叫做从n 个不同元素中取出m 个元素的一个排列. ⑫相同排列.如果;两个排列相同,不仅这两个排列的元素必须完全相同,而且排列的顺序也必须完全相同.⑬排列数.从n 个不同元素中取出m (m≤n )个元素排成一列,称为从n 个不同元素中取出m 个元素的一个排列. 从n 个不同元素中取出m 个元素的一个排列数,用符号m n A 表示. ⑭排列数公式:),,()!(!)1()1(N m n n m m n n m n n n A m∈≤-=+--=注意:!)!1(!n n n n -+=⋅ 规定0! = 1111--++=⋅+=m nmn m nmm mn mn mAA CA A A11--=m n m n nA A 规定10==nn n C C2. 含有可重元素......的排列问题. 对含有相同元素求排列个数的方法是:设重集S 有k 个不同元素a 1,a 2,…...a n 其中限重复数为n 1、n 2……n k ,且n = n 1+n 2+……n k , 则S 的排列个数等于!!...!!21k n n n n n =.例如:已知数字3、2、2,求其排列个数3!2!1)!21(=+=n 又例如:数字5、5、5、求其排列个数?其排列个数1!3!3==n.三、组合. 1. ⑪组合:从n 个不同的元素中任取m (m≤n )个元素并成一组,叫做从n 个不同元素中取出m 个元素的一个组合. ⑫组合数公式:)!(!!!)1()1(m n m n C m m n n n AA C mn m mm n mn-=+--==⑬两个公式:①;mn n mn CC -= ②m n m n m n C C C11+-=+①从n 个不同元素中取出m 个元素后就剩下n-m 个元素,因此从n 个不同元素中取出 n-m 个元素的方法是一一对应的,因此是一样多的就是说从n 个不同元素中取出n-m 个元素的唯一的一个组合.(或者从n+1个编号不同的小球中,n 个白球一个红球,任取m 个不同小球其不同选法,分二类,一类是含红球选法有1m n111m n C C C --=⋅一类是不含红球的选法有m n C ) ②根据组合定义与加法原理得;在确定n+1个不同元素中取m 个元素方法时,对于某一元素,只存在取与不取两种可能,如果取这一元素,则需从剩下的n 个元素中再取m-1个元素,所以有C 1-m n,如果不取这一元素,则需从剩余n 个元素中取出m 个元素,所以共有Cm n种,依分类原理有mn m n m n C C C11+-=+.⑭排列与组合的联系与区别.联系:都是从n 个不同元素中取出m 个元素.区别:前者是“排成一排”,后者是“并成一组”,前者有顺序关系,后者无顺序关系. ⑮①几个常用组合数公式nnn n n n C C C 221=+++1111112115314211112++--++++++-+=+==++=+++=+++k n kn k n kn m n m mn m mm mm mn n n n n n n n Cn C k nC kC C C C C C C C C C C C②常用的证明组合等式方法例. i. 裂项求和法. 如:)!1(11)!1(!43!32!21+-=++++n n n(利用!1)!1(1!1n n n n --=-)ii. 导数法. iii. 数学归纳法. iv. 倒序求和法.v. 递推法(即用mn m n m n C C C 11+-=+递推)如:413353433+=+++n n C C C C C .vi. 构造二项式. 如:nn n n n n C C C C 222120)()()(=+++证明:这里构造二项式n n n x x x 2)1()1()1(+=++其中n x 的系数,左边为22122211)()()(nn n n n nn n n n n nn nn n C C C C C CC CC C C +++=⋅++⋅+⋅+⋅-- ,而右边n nC2=四、排列、组合综合.1. I. 排列、组合问题几大解题方法及题型: ①直接法. ②排除法.③捆绑法:在特定要求的条件下,将几个相关元素当作一个元素来考虑,待整体排好之后再考虑它们“局部”的排列.它主要用于解决“元素相邻问题”,例如,一般地,n 个不同元素排成一列,要求其中某)(n m m ≤个元素必相邻的排列有m m m n m n A A ⋅+-+-11个.其中11+-+-m n m n A 是一个“整体排列”,而m m A 则是“局部排列”.又例如①有n 个不同座位,A 、B 两个不能相邻,则有排列法种数为-2n A 2211A A n ⋅-.②有n 件不同商品,若其中A 、B 排在一起有2211A A n n ⋅--. ③有n 件不同商品,若其中有二件要排在一起有112--⋅n n n A A . 注:①③区别在于①是确定的座位,有22A 种;而③的商品地位相同,是从n 件不同商品任取的2个,有不确定性.④插空法:先把一般元素排列好,然后把待定元素插排在它们之间或两端的空档中,此法主要解决“元素不相邻问题”.例如:n 个元素全排列,其中m 个元素互不相邻,不同的排法种数为多少?mm n m n mn A A 1+---⋅(插空法),当n – m+1≥m, 即m≤21+n 时有意义.⑤占位法:从元素的特殊性上讲,对问题中的特殊元素应优先排列,然后再排其他一般元素;从位置的特殊性上讲,对问题中的特殊位置应优先考虑,然后再排其他剩余位置.即采用“先特殊后一般”的解题原则.⑥调序法:当某些元素次序一定时,可用此法.解题方法是:先将n 个元素进行全排列有n n A 种,)(n m m 个元素的全排列有m m A 种,由于要求m 个元素次序一定,因此只能取其中的某一种排法,可以利用除法起到去调序的作用,即若n 个元素排成一列,其中m 个元素次序一定,共有mm nnA A 种排列方法.例如:n 个元素全排列,其中m 个元素顺序不变,共有多少种不同的排法?解法一:(逐步插空法)(m+1)(m+2)…n = n !/ m !;解法二:(比例分配法)mm nn A A /.⑦平均法:若把kn 个不同元素平均分成k 组,每组n 个,共有k kn nn nk n knACCC)1(-⋅.例如:从1,2,3,4中任取2个元素将其平均分成2组有几种分法?有3!224=C(平均分组就用不着管组与组之间的顺序问题了)又例如将200名运动员平均分成两组,其中两名种子选手必在一组的概率是多少? (!2/102022818C C C P=)注意:分组与插空综合. 例如:n 个元素全排列,其中某m 个元素互不相邻且顺序不变,共有多少种排法?有mm mm n mn m n A A A /1+---⋅,当n – m+1 ≥m, 即m≤21+n 时有意义.⑧隔板法:常用于解正整数解组数的问题.例如:124321=+++x x x x 的正整数解的组数就可建立组合模型将12个完全相同的球排成一列,在它们之间形成11个空隙中任选三个插入3块摸板,把球分成4个组.每一种方法所得球的数目依次为4321,,,x x x x 显然124321=+++x x x x ,故(4321,,,x x x x )是方程的一组解.反之,方程的任何一组解),,,(4321y y y y ,对应着惟一的一种在12个球之间插入隔板的方式(如图所示)故方程的解和插板的方法一一对应. 即方程的解的组数等于插隔板的方法数311C .注意:若为非负数解的x 个数,即用na a a ,...,21中i a 等于1+ix ,有A a a a A x x x x n n =-+-+-⇒=+++1...11...21321,进而转化为求a 的正整数解的个数为1-+n n A C .⑨定位问题:从n 个不同元素中每次取出k 个不同元素作排列规定某r 个元素都包含在内,并且都排在某r 个指定位置则有rk r n r r A A --.例如:从n 个不同元素中,每次取出m 个元素的排列,其中某个元素必须固定在(或不固定在)某一位置上,共有多少种排法? 固定在某一位置上:11--m n A;不在某一位置上:11---m n mn AA 或11111----⋅+m n m m n A A A (一类是不取出特殊元素a ,有mn A 1-,一类是取特殊元素a ,有从m-1个位置取一个位置,然后再从n-1个元素中取m-1,这与用插空法解决是一样的) ⑩指定元素排列组合问题.i. 从n 个不同元素中每次取出k 个不同的元素作排列(或组合),规定某r 个元素都包含在内 。
全排列算法解析(完整版)
void Permutation(int A[], int m, int n) {
int i, int temp; if(m = = n)
{ for(i = 0;i<n;i++) { if(i != n-1) printf("%d ",A[i]); //有加空格 else printf("%d" A[i]); //没加空格 } //直接输出,因为前 n-1 个数已经确定,递归到只有 1 个数。 printf("\n"); return;
排 列 组 合 公 式 及 排 列 组 合 算 法
算法中的排列与组合排列组合公式不含重复元素的排列组合含有重复元素的排列组合如果产生的组合和排列可以包含有重复的元素,其实这类问题在苏荷数学上是多种集的排列和组合问题。
多重集的排列问题设S是有k种不同类型对象的多重集合,每个元素都有无限的重复数。
那么s的r排列数目是krk^rkr.需要注意的是,只要每种元素的数目大于r,对于r组合来说就是无限多的。
怎么理解上面的定义呢,举个例子,冰淇淋有3种口味可以选择,我可以选择3种相同口味,也可以选择不同口味,每次选择即可相同也可不相同。
再举个例子抛硬币3次,很显然,可能会出现3次都是正面,硬币出现正反面是可重复的。
这很好理解,一次有k种选择,第二次有k?k种选择,……,第r次有krk^rkr种选择。
剑指offer中的面试题17.打印从1到最大的n位数,就是这类问题。
可以假设一共有0-9十种对象,每种对象都有无数个(无数个和大于等于n个一样,因为排列的最长长度是n),n位数就是十种对象的n排列,一共有10n10^n10n种。
其实很好理解,第一位数字有10种选择,第二位也有10种选择,… 第n位也有10种选择。
设s是多重集合,有k种类型的对象,且每种类型的有限重复数是n1,n2,……,nk。
s的大小是n=n1+n2+n3+……+nk。
那么s的全排列数目等于:result=n!(n1!?n2!?……?nk!)result=frac{n!}{(n1!*n2!*……*nk !)}result=(n1!?n2!?……?nk!)n!?例子:词MISSISSIPPI中字母的排列数是?分析:词含有的字母总个数是11,M:1,I:4,S:4,P:2。
所以result=11!-(1*4!*4!*2!).多重集合的组合设S是有k种类型对象的多重集合,每种元素均有无限的重复数。
那么S的r组合的个数等于:C(r+k-1,r)==C(r+k-1,k-1).需要注意的是,只要每种元素的数目大于r,对于r组合来说就是无限多的。
全排列算法之Perm算法实现
全排列算法之Perm算法实现 题⽬描述: 给定⼀个由不同的⼩写字母组成的字符串,输出这个字符串的所有全排列。
我们假设对于⼩写字母有'a' < 'b' < … < 'y' < 'z',⽽且给定的字符串中的字母已经按照从⼩到⼤的顺序排列。
输⼊: 输⼊只有⼀⾏,是⼀个由不同的⼩写字母组成的字符串,已知字符串的长度在1到6之间。
输出: 输出这个字符串的所有排列⽅式,每⾏⼀个排列。
要求字母序⽐较⼩的排列在前⾯。
字母序如下定义: 已知S = s1s2…sk , T = t1t2…tk,则S < T 等价于,存在p (1 <= p <= k),使得 s1 = t1, s2 = t2, …, sp - 1 = tp - 1, sp < tp成⽴。
样例输⼊: abc 样例输出: abc acb bac bca cab cba 提⽰: 每组样例输出结束后要再输出⼀个回车。
想必⼤家对perm递归算法求全排列并不陌⽣,但我贴出来的题⽬却不能⽤perm算法来解决,为什么呢?请容我慢慢道来,⾸先题⽬对全排列有着⾮常严格的顺序要求,即按字典顺序排列,就是这个perm算法是满⾜不了的(或许经过⼩⼩的改变是可以实现的,我们在这⾥就不讨论了)。
那么下来我来谈谈perm算法的核⼼思:举个例⼦,⽐如要你1的全排列,你肯定会说那还不简单啊,那么接下来加深难度求1,2的全排列,其实也不难,现在让你求1,2,3,4,5的全排列呢,还转得过来吗?现在我们可以这样想,3,4,5的全排列是以3开头的4,5的全排列组合和4开头的3,5的全排列组合以及以5开头的3,4全排列组合。
这就是perm算法的核⼼思想,列出⼀个通俗⼀点的式⼦ 从⽽可以推断,设⼀组数p = {r1, r2, r3, … ,rn}, 全排列为perm(p),pn = p - {rn}. 因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), … , rnperm(pn)。
含有重复元素的全排列问题
含有重复元素的全排列问题简介:本⽂主要介绍基于分治⽅式(递归)和枚举⽅式(循环)来构建指定字符串的全排列⽅法,两种⽅法都可以解决重复元素的全排列欢迎探讨,如有错误敬请指正如需转载,请注明出处1. 基于分治⽅式(递归实现)1)⼀个元素的全排列只有⼀种2)[A0, A1, A2]的全排列等于下⾯三个全排列的并集A0开头,拼接上[A1,A2]的所有全排列A1开头,拼接上[A0,A2]的所有全排列A2开头,拼接上[A0,A1]的所有全排列所以,对于[A0, A1, ……,An]的全排列,我们可以将问题转换成n个⼦问题:A0开头,拼接上[A1,A2 ……,An]的所有全排列A1开头,拼接上[A0,A2 ……,An]的所有全排列……An开头,拼接上[A0,A2 ……,A(n-1)]的所有全排列⽽每个⼦问题⼜可以继续向下转化成n-1个⼦问题,最终可以转化到只有⼀个元素的全排列问题。
对于数组中有重复元素的情况,我们只要保证,重复元素只能有⼀次作为⼦问题的开头元素,这样我们就可以避免重复计算。
2. 基于枚举⽅式(循环实现)如果我们将全排列按照⼤⼩顺序进⾏排序,假设我们知道了第i个排列是[A0, A1, A2, A3, ……],那么第i+1个排列就是⽐[A0, A1, A2, A3, ……]⼤,且最⼩的那个。
找到i+1个排列的步骤如下1)从后往前两两⽐较,找到第⼀个满⾜a[i]<a[i+1]的两个元素2)从a[i+1]开始往后找,找到⼀个⼤于a[i]中最⼩的⼀个元素,这个元素的下标记为j,交换a[i]和a[j]3)将[i+1, a.length-1]的元素全部逆序3. 代码实现下⾯是java代码的实现package interviewquestion;import java.util.HashSet;import java.util.LinkedList;import java.util.List;public class Permutation {//返回装有回字符串s的全排列的List对象public static List<String> byTraverse(String s){char[] chArr = s.toCharArray();List<String> list = new LinkedList<String>();byTraverse0(chArr, 0, list);return list;}private static void byTraverse0(char[] arr, int left, List<String> list){if(left >= arr.length-1){list.add(new String(arr));return;}//⽤于记录交换到left下标的每⼀个元素,防⽌计算重复的排列HashSet<Character> hs = new HashSet<Character>();for(int i = left; i < arr.length; i++){//arr[left]后⾯的每⼀个元素arr[i]都和arr[left]交换swap(arr, left, i);if(!hs.contains(arr[left])){hs.add(arr[left]);byTraverse0(arr, left+1, list);}//将left和i交换回来,防⽌遗漏,重复//已保证下⼀个交换到left下标的是未交换过的元素swap(arr, left, i);}}/*=================================================*///返回装有⼤于等于字符串s的全排列的List对象public static List<String> byNext(String s){char[] arr = s.toCharArray();List<String> list = new LinkedList<String>();list.add(s);while(next(arr)){list.add(new String(arr));}return list;}private static boolean next(char[] arr){boolean hasNext = false;int i;for(i = arr.length-2; i >= 0; i--){if(arr[i] < arr[i+1]){hasNext = true;break;}}//如果所有元素是从⼤到⼩排列,说明是最⼤的字符串if(!hasNext){return false;}//从i+1的下标往后找(必定是单调递减),找⼀个⽐arr[i]⼤的集合中最⼩的⼀个 int j;for(j = i+1; j < arr.length; j++){if(arr[j] <= arr[i]){break;}}j--;//交换这两个元素,然后逆序i+1以后的所有元素swap(arr, i, j);reverse(arr, i+1, arr.length-1);return true;}private static void reverse(char[] arr, int from, int to){for(int i = from, j = to; i < j; i++, j--){swap(arr, i, j);}}/*=================================================*/private static void swap(char[] chArr, int i, int j){char t = chArr[i];chArr[i] = chArr[j];chArr[j] = t;}public static void main(String[] args){List<String> list1 = Permutation.byNext("1233");System.out.println(list1);System.out.println(list1.size());System.out.println();List<String> list2 = Permutation.byTraverse("1233");System.out.println(list2);System.out.println(list2.size());}}运⾏结果[1233, 1323, 1332, 2133, 2313, 2331, 3123, 3132, 3213, 3231, 3312, 3321] 12[1233, 1323, 1332, 2133, 2313, 2331, 3213, 3231, 3123, 3132, 3312, 3321] 12。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
有重复元素的排列问题
1. 问题描述
设R={r1,r2,…rn}是要进行排列的n个元素。
其中元素r1,r2,…rn可能相同。
设计一个算法,列出R的所有不同排列。
算法设计:给定n及待排列的n个元素。
计算出这n个元素的所有不同排列。
2. 算法流程分析
设计一个递归算法生成n个元素的全排列。
设R={r1,r2,r3,……rn}的全排列为perm(R),由(r1)perm(R1),(r2)perm(R2),…,(rn)perm(Rn)构成。
如果这组数有重复的元素,在准备开始第i个元素打头的全排列序列时,即Swap(R[k],R[i])之前,先判断第i个元素是否在前面元素R[k…i-1]中出现过,未出现过,此过程照旧继续,若出现过,这次以i元素打头的排列输出跳过。
设 list[]={0,0,1},算法流程示意图如下:
3. 算法正确性证明
通过几组实例证明合法的输入可以得到正确的输出。
实例见附录第2部分。
4. 算法复杂度分析
n个元素的全排列若不考虑重复元素,有n!种不同的全排列,则时间复杂度为O(n!)。
若考虑重复元素,在最坏的情况下,重复元素出现的概率为0,则时间复杂度仍为O(n!)。
5.参考文献
[1] 王晓东编著,计算机算法设计与分析(第3版)。
北京:电子工业出版社,2007.5,P11-12
6.附录
(1)可执行代码如下:
#include<iostream.h>
template<class Type>
void perm(Type list[],int k,int m) {
if (k==m)
{
for (int i=0;i<=m;i++)
cout<<list[i]; cout<<endl; }
else
{
for(int i=k;i<=m;i++)
if(ch(list,k,i))
{
swap(list[k],list[i]);
perm(list,k+1,m);
swap(list[k],list[i]);
}
}
}
template<class Type>
inline void swap(Type &a,Type &b) {
Type temp=a;a=b;b=temp;
}
void main()
{
int list[3]={0,1,1};
perm(list,0,2);
}
template<class Type>
int ch(Type list[],int k,int i) {if(i>k)
for(int t=k;t<i;t++)
if(list[t]==list[i])
return 0;
return 1;
}
(2)输入输出实例
输入1 3 5 5
输出如下:
1 3 5 5
1 5 3 5
1 5 5 3 3 1 5 5 3 5 1 5 3 5 5 1 5 1 3 5 5 1 5 3 5 3 1 5 5 3 5 1 5 5 1 3 5 5 3 1。