1.題目html
輸入一個字符串,打印出該字符串中字符的全排列。例如輸入字符串abc,則打印出[cab, abc, cba, bca, bac, acb]java
題目難度適中,能夠考察遞歸、非遞歸、是否有無重複字符的全排列等。算法
2.思路數組
對於全排列,好比有3個字符abc,共有3!=6種排列.ide
首先分析出數學遞歸公式。
假設abcde是一個輸入參數,輸出的值則是一個全排列集合。能夠有:spa
1 f(abcde)=a+f(bcde) 2 f(bcde)=b+f(cde) 3 f(cde)=c+f(de) 4 f(de)={de,ed}
定義:code
3.僞代碼實現htm
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)。blog
定義:排序
時間複雜度: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(參考此博文的介紹)
這種類型的題目推廣開來就是:求一個元素組中,全部知足必定條件的排列。
對於這種問題,在沒有很好的剪枝的前提下,每每採用先求出全部排列,而後一一檢驗是否知足條件。
相似的題目還有八皇后問題,求全部八皇后的排放方式。