求全排列

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求全排列相关的知识,希望对你有一定的参考价值。

参考:

1. STL系列之十 全排列(百度迅雷笔试题)

2. 全排列算法非递归实现和递归实现 (C++)

3. [算法]列车算法 

题目要求:

写一个函数, 如 Foo(const char *str), 打印出 str 的全排列, 
如 abc 的全排列: abc, acb, bca, dac, cab, cba

一.全排列的递归实现

为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑123和132如何得出:它们的最高位都固定为1(或者说以1为前缀),后边跟上{2,3}的全排列(至于{2,3}的全排列怎么求,则靠递归来完成);213和231同理:以2为前缀,后边跟上{1,3}的全排列;312和321:以3为前缀,后边跟上{1,2}的全排列。

形式化一点的表述——

E= {e1 , ..., en }表示个元素的集合,我们的目标是生成该集合的所有排列方式。

Ei E中移去元素以后所获得的集合,

perm (X) 表示集合中元素的排列方式,

ei . p e r m(X)表示在perm (X) 中的每个排列方式的前面均加上ei 以后所得到的排列方式。

举例——

如果E= {a, b, c},那么E1= {b, c},perm (E1 ) = ( b cc b),e1.perm (E1) = (a b ca c b)。

对于递归的基本部分,采用= 1。当只有一个元素时,只可能产生一种排列方式,所以perm (E) = ( e),其中中的唯一元素。

> 1时,perm (E) = e1.perm (E1 ) +e2.perm(E2 ) +e3.perm (E3) + ? +en .perm (En )。这种递归定义形式是采用perm (X) 来定义perm (E), 其中每个包含n- 1个元素。至此,一个完整的递归定义所需要的基本部分和递归部分都已完成。

也就是说——

n= 3并且E=(abc)时,按照前面的递归定义可得perm (E) =a.perm ( {bc} ) +b.perm ( {a,c} ) +c.perm ( {ab} )

同样,按照递归定义有perm ( {bc} ) =b.perm ( {c} ) +c.perm ( {b}),

所以a.perm ( {bc} )ab.perm ( {c} ) + ac.perm ( {b}) = a b . c ac.b = (a b ca c b)。

同理可得 b.perm ( {ac}) = ... = (b a cb c a),c.perm ( {ab}) = ... = (c a bc b a)。

所以perm (E) = (a b ca c bb a cb c a,c a bc b a)。

技术分享
 1 public class Permutation {
 2     
 3     // 生成arr[k:m]的所有排列方式
 4     private static void perm(char[] arr, int k, int m) {
 5          if (k == m)    // 得到了一个排列方式
 6              System.out.println(Arrays.toString(arr));
 7          else {            
 8              // arr[k:m]有多种排列方式,递归地求出来
 9              for (int i = k; i <= m; i++) {
10                  char t = arr[i];  arr[i] = arr[k]; arr[k] = t;
11                  perm(arr, k+1, m);
12                  t = arr[i];  arr[i] = arr[k]; arr[k] = t;
13              }
14          }
15     }
16     
17     private static void perm(char[] arr) {
18         perm(arr, 0, arr.length-1);
19     }
20 
21     public static void main(String[] args) {
22         char[] sequence = new String("abcd").toCharArray();
23         perm(sequence);
24     }
25 
26 }
View Code

 

总结

找到递归关系,把perm(E)问题转化为n个perm(X)问题,其中每个包含n- 1个元素。

以上是关于求全排列的主要内容,如果未能解决你的问题,请参考以下文章

求全排列(数组有重复元素和数组无重复元素) 回溯 递归

LeetCode46 回溯算法求全排列,这次是真全排列

c++dfs求全排列,求详细解释

专题训练 1001 求全排列

求全排列的两种方法

求全排列的两种方法