1.题目
输入一个字符串,打印出该字符串中字符的全排列。例如输入字符串abc,则打印出[cab, abc, cba, bca, bac, acb]
题目难度适中,可以考察递归、非递归、是否有无重复字符的全排列等。
2.思路
对于全排列,比如有3个字符abc,共有3!=6种排列.
首先分析出数学递归公式。
假设abcde是一个输入参数,输出的值则是一个全排列集合。可以有:
1 f(abcde)=a+f(bcde) 2 f(bcde)=b+f(cde) 3 f(cde)=c+f(de) 4 f(de)={de,ed}
定义:
- f(abc) : abc的全排列
- d+f(abc) : d插入到f(abc)全排列的所有字符串的任意位置
3.伪代码实现
1 FullPermutation(A, p, r) 2 if r-p <=1 3 add(set, A[pr]) 4 add(set, A[rp]) 5 return set 6 return A[p] + FullPermutation(A, p+1, r)
全排序一个完整的字符数组A,最初的调用是FullPermutation(A, 0, length[A]-1)。
定义:
- A : 带全排列的字符数组
- p, r : 待全排列的子数组下标
- set : 存放全排列的集合
- add : 为set增加一个字符串
时间复杂度:O(n!)
4.Java代码实现
伪代码写算法的好处:不用关心代码的细节,便于理解和记忆。

1 import java.util.HashSet; 2 import java.util.Set; 3 4 public class FullPermutation { 5 public static void main(String[] args) { 6 char[] A = "abcd".toCharArray(); 7 Set<String> set = fullPer(A, 0, A.length - 1); 8 System.out.println("set:" + set + "\nSize:" + set.size()); 9 } 10 11 /** 12 * @param A 待全排列的字符数组 13 * @param p 子数组左边界 14 * @param r 子数组右边界 15 * @return 全排列的集合 16 */ 17 static Set<String> fullPer(char[] A, int p, int r) { 18 if (r - p <= 1) { 19 char[] cs = new char[2]; 20 cs[0] = A[p]; 21 cs[1] = A[r]; 22 Set<String> set = new HashSet<String>(); 23 set.add(new String(cs)); 24 cs[0] = A[r]; 25 cs[1] = A[p]; 26 set.add(new String(cs)); 27 return set; 28 } 29 return insertChar(A[p], fullPer(A, p + 1, r)); 30 } 31 32 /** 33 * 将字符 c 插入到集合setIn所有字符串的任意位置 34 * @param c char 35 * @param setIn Set<String> 36 * @return Set<String> 37 */ 38 private static Set<String> insertChar(char c, Set<String> setIn) { 39 Set<String> set = new HashSet<String>(); 40 for (String s : setIn) { 41 char[] cs = s.toCharArray(); 42 int len = cs.length + 1; 43 char[] result = new char[len]; 44 for (int i = 0; i < len; i++) { 45 result[i] = c; 46 for (int j = 0, k = 0; k < len - 1; j++, k++) { 47 if (j == i) 48 j++; 49 result[j] = cs[k]; 50 } 51 set.add(new String(result)); 52 } 53 } 54 return set; 55 } 56 }
5.更上一层楼
有一种算法可以得到排序字符串的下一个字典序,利用它,可以得到字符串的全排列。
求字典序的算法叫做康托集。
6.More(参考此博文的介绍)
这种类型的题目推广开来就是:求一个元素组中,所有满足一定条件的排列。
对于这种问题,在没有很好的剪枝的前提下,往往采用先求出所有排列,然后一一检验是否满足条件。
类似的题目还有八皇后问题,求所有八皇后的排放方式。