字符串的全排列问题

题目:

  编写一个方法,确定某字符串的所有排列组合。

  解法一:

    

  代码:

 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 }

  结果:

    

扫描二维码关注公众号,回复: 5138930 查看本文章

例题:

  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 }

  结果:

    

猜你喜欢

转载自www.cnblogs.com/xiaoyh/p/10345064.html