字符串的全排列問題


題目:

  編寫一個方法,確定某字符串的所有排列組合。

  解法一:

    

  代碼:

 1 import java.util.ArrayList;
 2 
 3 public class 全排列1 {
 4 
 5     public static void main(String[] args) {
 6         ArrayList<String> res = getPermutation0("abcd",4-1);
 7         System.out.println(res.size());
 8         System.out.println(res);
 9         System.out.println("=====================================");
10         res = getPermutation1("abcd");
11         System.out.println(res.size());
12         System.out.println(res);
13     }
14     
15     // 迭代法的遞歸形式
16     public static ArrayList<String> getPermutation0(String A,int n){
17         if (n==0) {
18             ArrayList<String> res = new ArrayList<>();
19             res.add(A.charAt(n)+"");
20             return res;
21         }
22         ArrayList<String> res = getPermutation0(A, n-1);
23         char c = A.charAt(n);
24         ArrayList<String> res_new = new ArrayList<>();
25         for (String str : res) {// 訪問上一趟集合中的每個字符串
26             // 插入到每個位置,形成一個新串
27             String newStr = c + str;// 加在前面
28             res_new.add(newStr);
29             newStr = str + c;// 加在后面
30             res_new.add(newStr);
31             // 加在中間
32             for (int j = 1; j < str.length(); j++) {
33                 newStr = str.substring(0, j) + c + str.substring(j);
34                 res_new.add(newStr);
35             }
36         }
37         return res_new;
38     }
39     
40     /*逐步生成大法-迭代法*/
41     public static ArrayList<String> getPermutation1(String A) {
42         int n = A.length();
43         ArrayList<String> res = new ArrayList<>();
44         res.add(A.charAt(0) + "");// 初始化,包含第一個字符
45 
46         for (int i = 1; i < n; i++) {// 第二個字符插入到前面生成集合的每個元素里面
47             ArrayList<String> res_new = new ArrayList<>();
48             char c = A.charAt(i);// 新字符
49             for (String str : res) {// 訪問上一趟集合中的每個字符串
50                 // 插入到每個位置,形成一個新串
51                 String newStr = c + str;// 加在前面
52                 res_new.add(newStr);
53                 newStr = str + c;// 加在后面
54                 res_new.add(newStr);
55                 // 加在中間
56                 for (int j = 1; j < str.length(); j++) {
57                     newStr = str.substring(0, j) + c + str.substring(j);
58                     res_new.add(newStr);
59                 }
60             }
61             res = res_new;// 更新
62 
63         }
64         return res;
65     }
66 
67 }

  結果:

    

   解法二:交換法,大體意思就是不開辟新的輔助空間,直接在原有的數組中進行兩個元素的交換即可,但是要注意這種方法必須要進行回溯。

   代碼:

 1 import java.util.ArrayList;
 2 import java.util.Arrays;
 3 
 4 public class 全排列2 {
 5 
 6     public static void main(String[] args) {
 7         ArrayList<String> res = getPermutation("123");
 8         System.out.println(res.size());
 9         System.out.println(res);
10     }
11 
12     static ArrayList<String> res = new ArrayList<>();
13 
14     public static ArrayList<String> getPermutation(String A) {
15         char[] arr = A.toCharArray();
16         Arrays.sort(arr);// abc
17         getPermutationCore(arr, 0);
18         return res;
19     }
20 
21     private static void getPermutationCore(char[] arr, int k) {
22         if (k == arr.length) {// 排好了一種情況,遞歸的支路走到底了
23             res.add(new String(arr));
24         }
25 
26         // 從k位開始的每個字符,都嘗試放在新排列的k這個位置
27         for (int i = k; i < arr.length; i++) {
28             swap(arr, k, i);// 把后面每個字符換到k位
29             getPermutationCore(arr, k + 1);
30             swap(arr, k, i);// 回溯
31         }
32     }
33 
34     // 交換位置
35     static void swap(char[] arr, int i, int j) {
36         char tmp = arr[i];
37         arr[i] = arr[j];
38         arr[j] = tmp;
39     }
40 
41 }

  結果:

    

例題:

  LeetCode60 n個數的排列組合找出第k個排列。

  思路:在上面的代碼中我們雖然已經完成了n的元素的全排列,可是它的結果並不是按照字典序排列,那對於這道題目來說,按照上面的思路就很難完成了,當然我們也可以對上面的解法的答案再進行排序,這也算是一種方法。這里要介紹的是一種叫做前綴法的方法。思路就是每次從頭順序掃描源數組(當然要先把源數組排序),只要該元素不在前綴里面,那么就把這個元素附加到前綴的后面形成新的前綴,直到這個前綴的長度等於源串的長度就不再繼續加下去了。然后繼續這樣循環下去就能得到按照字典序排列的全排列,在循環過程中依次計數即可,這樣就能找出第k個排列了。

  代碼:

 1 public class 全排列3 {
 2 
 3     public static void main(String[] args) {
 4         String s = "123";
 5         permutation("", s.toCharArray());
 6     }
 7 
 8     final static int k = 3;
 9     static int count = 0;
10 
11     private static void permutation(String prefix, char[] arr) {
12         if (prefix.length() == arr.length) {// 前綴的長度==字符集的長度,一個排列就完成了
13             // System.out.println(prefix);
14             count++;
15             if (count == k) {
16                 System.out.println("-------:" + prefix);
17                 System.exit(0);
18             }
19         }
20         // 每次都從頭掃描,只要該字符可用,我們就附加到前綴后面,前綴變長了
21         for (int i = 0; i < arr.length; i++) {
22             char ch = arr[i];
23             // 這個字符可用:在pre中出現次數<在字符集中的出現次數 以防有元素重復的情況
24             if (count(prefix, ch) < count(arr, ch)) {
25                 permutation(prefix + ch, arr);
26             }
27         }
28     }
29 
30     private static int count(char[] arr, char ch) {
31         int cnt = 0;
32         for (char c : arr) {
33             if (c == ch)
34                 cnt++;
35         }
36         return cnt;
37     }
38 
39     private static int count(String str, char ch) {
40         int cnt = 0;
41         for (int i = 0; i < str.length(); i++) {
42             if (str.charAt(i) == ch)
43                 cnt++;
44         }
45         return cnt;
46     }
47 
48 }

  結果:

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM