Generating all permutations of a given string

前端 未结 30 1603
我寻月下人不归
我寻月下人不归 2020-11-21 06:35

What is an elegant way to find all the permutations of a string. E.g. permutation for ba, would be ba and ab, but what about longer st

相关标签:
30条回答
  • 2020-11-21 06:37
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Scanner;
    public class hello {
        public static void main(String[] args) throws IOException {
            hello h = new hello();
            h.printcomp();
        }
          int fact=1;
        public void factrec(int a,int k){
            if(a>=k)
            {fact=fact*k;
            k++;
            factrec(a,k);
            }
            else
            {System.out.println("The string  will have "+fact+" permutations");
            }
            }
        public void printcomp(){
            String str;
            int k;
            Scanner in = new Scanner(System.in);
            System.out.println("enter the string whose permutations has to b found");
            str=in.next();
            k=str.length();
            factrec(k,1);
            String[] arr =new String[fact];
            char[] array = str.toCharArray();
            while(p<fact)
            printcomprec(k,array,arr);
                // if incase u need array containing all the permutation use this
                //for(int d=0;d<fact;d++)         
            //System.out.println(arr[d]);
        }
        int y=1;
        int p = 0;
        int g=1;
        int z = 0;
        public void printcomprec(int k,char array[],String arr[]){
            for (int l = 0; l < k; l++) {
                for (int b=0;b<k-1;b++){
                for (int i=1; i<k-g; i++) {
                    char temp;
                    String stri = "";
                    temp = array[i];
                    array[i] = array[i + g];
                    array[i + g] = temp;
                    for (int j = 0; j < k; j++)
                        stri += array[j];
                    arr[z] = stri;
                    System.out.println(arr[z] + "   " + p++);
                    z++;
                }
                }
                char temp;
                temp=array[0];
                array[0]=array[y];
                array[y]=temp;
                if (y >= k-1)
                    y=y-(k-1);
                else
                    y++;
            }
            if (g >= k-1)
                g=1;
            else
                g++;
        }
    
    }
    
    0 讨论(0)
  • 2020-11-21 06:40

    Use recursion.

    • Try each of the letters in turn as the first letter and then find all the permutations of the remaining letters using a recursive call.
    • The base case is when the input is an empty string the only permutation is the empty string.
    0 讨论(0)
  • 2020-11-21 06:40

    Another simple way is to loop through the string, pick the character that is not used yet and put it to a buffer, continue the loop till the buffer size equals to the string length. I like this back tracking solution better because:

    1. Easy to understand
    2. Easy to avoid duplication
    3. The output is sorted

    Here is the java code:

    List<String> permute(String str) {
      if (str == null) {
        return null;
      }
    
      char[] chars = str.toCharArray();
      boolean[] used = new boolean[chars.length];
    
      List<String> res = new ArrayList<String>();
      StringBuilder sb = new StringBuilder();
    
      Arrays.sort(chars);
    
      helper(chars, used, sb, res);
    
      return res;
    }
    
    void helper(char[] chars, boolean[] used, StringBuilder sb, List<String> res) {
      if (sb.length() == chars.length) {
        res.add(sb.toString());
        return;
      }
    
      for (int i = 0; i < chars.length; i++) {
        // avoid duplicates
        if (i > 0 && chars[i] == chars[i - 1] && !used[i - 1]) {
          continue;
        }
    
        // pick the character that has not used yet
        if (!used[i]) {
          used[i] = true;
          sb.append(chars[i]);
    
          helper(chars, used, sb, res);
    
          // back tracking
          sb.deleteCharAt(sb.length() - 1);
          used[i] = false;
        }
      }
    }
    

    Input str: 1231

    Output list: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}

    Noticed that the output is sorted, and there is no duplicate result.

    0 讨论(0)
  • 2020-11-21 06:41

    We can use factorial to find how many strings started with particular letter.

    Example: take the input abcd. (3!) == 6 strings will start with every letter of abcd.

    static public int facts(int x){
        int sum = 1;
        for (int i = 1; i < x; i++) {
            sum *= (i+1);
        }
        return sum;
    }
    
    public static void permutation(String str) {
        char[] str2 = str.toCharArray();
        int n = str2.length;
        int permutation = 0;
        if (n == 1) {
            System.out.println(str2[0]);
        } else if (n == 2) {
            System.out.println(str2[0] + "" + str2[1]);
            System.out.println(str2[1] + "" + str2[0]);
        } else {
            for (int i = 0; i < n; i++) {
                if (true) {
                    char[] str3 = str.toCharArray();
                    char temp = str3[i];
                    str3[i] = str3[0];
                    str3[0] = temp;
                    str2 = str3;
                }
    
                for (int j = 1, count = 0; count < facts(n-1); j++, count++) {
                    if (j != n-1) {
                        char temp1 = str2[j+1];
                        str2[j+1] = str2[j];
                        str2[j] = temp1;
                    } else {
                        char temp1 = str2[n-1];
                        str2[n-1] = str2[1];
                        str2[1] = temp1;
                        j = 1;
                    } // end of else block
                    permutation++;
                    System.out.print("permutation " + permutation + " is   -> ");
                    for (int k = 0; k < n; k++) {
                        System.out.print(str2[k]);
                    } // end of loop k
                    System.out.println();
                } // end of loop j
            } // end of loop i
        }
    }
    
    0 讨论(0)
  • 2020-11-21 06:42

    Let's use input abc as an example.

    Start off with just the last element (c) in a set (["c"]), then add the second last element (b) to its front, end and every possible positions in the middle, making it ["bc", "cb"] and then in the same manner it will add the next element from the back (a) to each string in the set making it:

    "a" + "bc" = ["abc", "bac", "bca"]  and  "a" + "cb" = ["acb" ,"cab", "cba"] 
    

    Thus entire permutation:

    ["abc", "bac", "bca","acb" ,"cab", "cba"]
    

    Code:

    public class Test 
    {
        static Set<String> permutations;
        static Set<String> result = new HashSet<String>();
    
        public static Set<String> permutation(String string) {
            permutations = new HashSet<String>();
    
            int n = string.length();
            for (int i = n - 1; i >= 0; i--) 
            {
                shuffle(string.charAt(i));
            }
            return permutations;
        }
    
        private static void shuffle(char c) {
            if (permutations.size() == 0) {
                permutations.add(String.valueOf(c));
            } else {
                Iterator<String> it = permutations.iterator();
                for (int i = 0; i < permutations.size(); i++) {
    
                    String temp1;
                    for (; it.hasNext();) {
                        temp1 = it.next();
                        for (int k = 0; k < temp1.length() + 1; k += 1) {
                            StringBuilder sb = new StringBuilder(temp1);
    
                            sb.insert(k, c);
    
                            result.add(sb.toString());
                        }
                    }
                }
                permutations = result;
                //'result' has to be refreshed so that in next run it doesn't contain stale values.
                result = new HashSet<String>();
            }
        }
    
        public static void main(String[] args) {
            Set<String> result = permutation("abc");
    
            System.out.println("\nThere are total of " + result.size() + " permutations:");
            Iterator<String> it = result.iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-21 06:42

    This can be done iteratively by simply inserting each letter of the string in turn in all locations of the previous partial results.

    We start with [A], which with B becomes [BA, AB], and with C, [CBA, BCA, BAC, CAB, etc].

    The running time would be O(n!), which, for the test case ABCD, is 1 x 2 x 3 x 4.

    In the above product, the 1 is for A, the 2 is for B, etc.

    Dart sample:

    void main() {
    
      String insertAt(String a, String b, int index)
      {
        return a.substring(0, index) + b + a.substring(index);
      }
    
      List<String> Permute(String word) {
    
        var letters = word.split('');
    
        var p_list = [ letters.first ];
    
        for (var c in letters.sublist(1)) {
    
          var new_list = [ ];
    
          for (var p in p_list)
            for (int i = 0; i <= p.length; i++)
              new_list.add(insertAt(p, c, i));
    
          p_list = new_list;
        }
    
        return p_list;
      }
    
      print(Permute("ABCD"));
    
    }
    
    0 讨论(0)
提交回复
热议问题