• 字符串的全排列问题


    题目:

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

      解法一:

        

      代码:

     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 }

      结果:

        

  • 相关阅读:
    MySQL之ERROR 1558 (HY000): Column count of mysql.user is wrong.解决方案
    手动发布本地jar包到Nexus私服
    Git的常用命令
    手游录屏直播技术详解 | 直播 SDK 性能优化实践
    【容器云】十分钟快速构建 Influxdb+cadvisor+grafana 监控
    【容器云】传统金融企业的 Docker 实践
    直播推流端弱网优化策略 | 直播 SDK 性能优化实践
    云存储之覆盖上传——七牛云
    「视频直播技术详解」系列之七:直播云 SDK 性能测试模型
    「视频直播技术详解」系列之六:现代播放器原理
  • 原文地址:https://www.cnblogs.com/xiaoyh/p/10345064.html
Copyright © 2020-2023  润新知