Generate list of all possible permutations of a string

后端 未结 30 2548
故里飘歌
故里飘歌 2020-11-22 15:10

How would I go about generating a list of all possible permutations of a string between x and y characters in length, containing a variable list of characters.

Any l

相关标签:
30条回答
  • 2020-11-22 15:38

    I'm not sure why you would want to do this in the first place. The resulting set for any moderately large values of x and y will be huge, and will grow exponentially as x and/or y get bigger.

    Lets say your set of possible characters is the 26 lowercase letters of the alphabet, and you ask your application to generate all permutations where length = 5. Assuming you don't run out of memory you'll get 11,881,376 (i.e. 26 to the power of 5) strings back. Bump that length up to 6, and you'll get 308,915,776 strings back. These numbers get painfully large, very quickly.

    Here's a solution I put together in Java. You'll need to provide two runtime arguments (corresponding to x and y). Have fun.

    public class GeneratePermutations {
        public static void main(String[] args) {
            int lower = Integer.parseInt(args[0]);
            int upper = Integer.parseInt(args[1]);
    
            if (upper < lower || upper == 0 || lower == 0) {
                System.exit(0);
            }
    
            for (int length = lower; length <= upper; length++) {
                generate(length, "");
            }
        }
    
        private static void generate(int length, String partial) {
            if (length <= 0) {
                System.out.println(partial);
            } else {
                for (char c = 'a'; c <= 'z'; c++) {
                    generate(length - 1, partial + c);
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 15:39

    It's better to use backtracking

    #include <stdio.h>
    #include <string.h>
    
    void swap(char *a, char *b) {
        char temp;
        temp = *a;
        *a = *b;
        *b = temp;
    }
    
    void print(char *a, int i, int n) {
        int j;
        if(i == n) {
            printf("%s\n", a);
        } else {
            for(j = i; j <= n; j++) {
                swap(a + i, a + j);
                print(a, i + 1, n);
                swap(a + i, a + j);
            }
        }
    }
    
    int main(void) {
        char a[100];
        gets(a);
        print(a, 0, strlen(a) - 1);
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 15:39

    permute (ABC) -> A.perm(BC) -> A.perm[B.perm(C)] -> A.perm[(*BC), (CB*)] -> [(*ABC), (BAC), (BCA*), (*ACB), (CAB), (CBA*)] To remove duplicates when inserting each alphabet check to see if previous string ends with the same alphabet (why? -exercise)

    public static void main(String[] args) {
    
        for (String str : permStr("ABBB")){
            System.out.println(str);
        }
    }
    
    static Vector<String> permStr(String str){
    
        if (str.length() == 1){
            Vector<String> ret = new Vector<String>();
            ret.add(str);
            return ret;
        }
    
        char start = str.charAt(0);
        Vector<String> endStrs = permStr(str.substring(1));
        Vector<String> newEndStrs = new Vector<String>();
        for (String endStr : endStrs){
            for (int j = 0; j <= endStr.length(); j++){
                if (endStr.substring(0, j).endsWith(String.valueOf(start)))
                    break;
                newEndStrs.add(endStr.substring(0, j) + String.valueOf(start) + endStr.substring(j));
            }
        }
        return newEndStrs;
    }
    

    Prints all permutations sans duplicates

    0 讨论(0)
  • 2020-11-22 15:40

    This is a translation of Mike's Ruby version, into Common Lisp:

    (defun perms (x y original-string)
      (loop with all = (list "")
            with current-array = (list "")
            for iteration from 1 to y
            do (loop with next-array = nil
                     for string in current-array
                     do (loop for c across original-string
                              for value = (concatenate 'string string (string c))
                              do (push value next-array)
                                 (push value all))
                        (setf current-array (reverse next-array)))
            finally (return (nreverse (delete-if #'(lambda (el) (< (length el) x)) all)))))
    

    And another version, slightly shorter and using more loop facility features:

    (defun perms (x y original-string)
      (loop repeat y
            collect (loop for string in (or (car (last sets)) (list ""))
                          append (loop for c across original-string
                                       collect (concatenate 'string string (string c)))) into sets
            finally (return (loop for set in sets
                                  append (loop for el in set when (>= (length el) x) collect el)))))
    
    0 讨论(0)
  • 2020-11-22 15:40

    Ruby answer that works:

    class String
      def each_char_with_index
        0.upto(size - 1) do |index|
          yield(self[index..index], index)
        end
      end
      def remove_char_at(index)
        return self[1..-1] if index == 0
        self[0..(index-1)] + self[(index+1)..-1]
      end
    end
    
    def permute(str, prefix = '')
      if str.size == 0
        puts prefix
        return
      end
      str.each_char_with_index do |char, index|
        permute(str.remove_char_at(index), prefix + char)
      end
    end
    
    # example
    # permute("abc")
    
    0 讨论(0)
  • 2020-11-22 15:40

    c# iterative:

    public List<string> Permutations(char[] chars)
        {
            List<string> words = new List<string>();
            words.Add(chars[0].ToString());
            for (int i = 1; i < chars.Length; ++i)
            {
                int currLen = words.Count;
                for (int j = 0; j < currLen; ++j)
                {
                    var w = words[j];
                    for (int k = 0; k <= w.Length; ++k)
                    {
                        var nstr = w.Insert(k, chars[i].ToString());
                        if (k == 0)
                            words[j] = nstr;
                        else
                            words.Add(nstr);
                    }
                }
            }
            return words;
        }
    
    0 讨论(0)
提交回复
热议问题