generating Variations without repetitions / Permutations in java

后端 未结 10 962
半阙折子戏
半阙折子戏 2021-01-02 07:33

I have to generate all variations without repetitions made of digits 0 - 9.

Length of them could be from 1 to 10. I really don\'t know how to solve it, especially ho

相关标签:
10条回答
  • 2021-01-02 07:45

    There is one solution which is not from mine, but it is very nice and sophisticated.

        package permutations;
    
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * @author Vladimir Hajek
     *
     */
    public class PermutationSimple {
        private static final int MAX_NUMBER = 3;
    
        Set<String> results = new HashSet<>(0);
    
        /**
         * 
         */
        public PermutationSimple() {
            // TODO Auto-generated constructor stub
        }
    
        /**
         * @param availableNumbers
         * @return
         */
        public static List<String> generatePermutations(Set<Integer> availableNumbers) {
            List<String> permutations = new LinkedList<>();
    
            for (Integer number : availableNumbers) {
                Set<Integer> numbers = new HashSet<>(availableNumbers);
                numbers.remove(number);
    
                if (!numbers.isEmpty()) {
                    List<String> childPermutations = generatePermutations(numbers);
                    for (String childPermutation : childPermutations) {
                        String permutation = number + childPermutation;
                        permutations.add(permutation);
                    }
                } else {
                    permutations.add(number.toString());
                }
            }
    
            return permutations;
        }
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            Set<Integer> availableNumbers = new HashSet<>(0);
    
            for (int i = 1; i <= MAX_NUMBER; i++) {
                availableNumbers.add(i);
            }
    
            List<String> permutations = generatePermutations(availableNumbers);
            for (String permutation : permutations) {
                System.out.println(permutation);
            }
    
        }
    }
    

    I think, this is the excellent solution.

    0 讨论(0)
  • 2021-01-02 07:46

    The code for this is similar to the one without duplicates, with the addition of an if-else statement.Check this code

    In the above code,Edit the for loop as follows

    for (j = i; j <= n; j++)
    {
    
    if(a[i]!=a[j] && !is_duplicate(a,i,j))              
        {
            swap((a+i), (a+j));
            permute(a, i+1, n);
            swap((a+i), (a+j)); 
        }
        else if(i!=j)  {}  // if no duplicate is present , do nothing           
        else permute(a,i+1,n);  // skip the ith character
    }
    
    bool is_duplicate(int *a,int i,int j) 
    {
         if a[i] is present between a[j]...a[i] 
            return 1;
        otherwise
            return 0;
    
    }
    

    worked for me

    0 讨论(0)
  • 2021-01-02 07:55
    def find(alphabet, alpha_current, str, str_current, max_length, acc):
      
      if (str_current == max_length):
        acc.append(''.join(str))
        return
      
      for i in range(alpha_current, len(alphabet)):
        str[str_current] = alphabet[i]
        
        alphabet[i], alphabet[alpha_current] = alphabet[alpha_current], alphabet[i]
        
        find(alphabet, alpha_current+1, str, str_current+1, max_length, acc)
        
        alphabet[i], alphabet[alpha_current] = alphabet[alpha_current], alphabet[i]
      
      return
    
    max_length = 4
    str = [' ' for i in range(max_length)]
    acc = list()
    find(list('absdef'), 0, str, 0, max_length, acc)
    
    for i in range(len(acc)):
      print(acc[i])
    
    print(len(acc))
    
    0 讨论(0)
  • 2021-01-02 08:00

    using Dollar it is simple:

    @Test
    public void generatePermutations() {
        // digits is the string "0123456789"
        String digits = $('0', '9').join();
    
        // then generate 10 permutations
        for (int i : $(10)) {
            // shuffle, the cut (0, 4) in order to get a 4-char permutation
            System.out.println($(digits).shuffle().slice(4));
        }
    }
    
    0 讨论(0)
  • 2021-01-02 08:01

    I have created the following code for generating permutations where ordering is important and with no repetition. It makes use of generics for permuting any type of object:

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    public class Permutations {
    
        public static <T> Collection<List<T>> generatePermutationsNoRepetition(Set<T> availableNumbers) {
            Collection<List<T>> permutations = new HashSet<>();
    
            for (T number : availableNumbers) {
                Set<T> numbers = new HashSet<>(availableNumbers);
                numbers.remove(number);
    
                if (!numbers.isEmpty()) {
                    Collection<List<T>> childPermutations = generatePermutationsNoRepetition(numbers);
                    for (List<T> childPermutation : childPermutations) {
                        List<T> permutation = new ArrayList<>();
                        permutation.add(number);
                        permutation.addAll(childPermutation);
                        permutations.add(permutation);
                    }
                } else {
                    List<T> permutation = new ArrayList<>();
                    permutation.add(number);
                    permutations.add(permutation);
                }
            }
    
            return permutations;
        }
    }
    
    0 讨论(0)
  • 2021-01-02 08:01

    Permutation without repetition is based on theorem, that amount of results is factorial of count of elements (in this case numbers). In your case 10! is 10*9*8*7*6*5*4*3*2*1 = 3628800. The proof why it is exactly right is right solution for generation also. Well so how. On first position i.e. from left you can have 10 numbers, on the second position you can have only 9 numbers, because one number is on the position on the left and we cannot repeat the same number etc. (the proof is done by mathematical induction). So how to generate first ten results? According my knowledges, he simplest way is to use cyclic shift. It means the order of number shift to the left on one position (or right if you want) and the number which overflow to put on the empty place. It means for first ten results:

    10 9 8 7 6 5 4 3 2 1
    9 8 7 6 5 4 3 2 1 10
    8 7 6 5 4 3 2 1 10 9
    7 6 5 4 3 2 1 10 9 8
    6 5 4 3 2 1 10 9 8 7
    5 4 3 2 1 10 9 8 7 6
    ...

    The first line is basic sample, so it is the good idea to put it into set before generation. Advantage is, that in the next step you will have to solve the same problem to avoid undesirable duplicities.

    In next step recursively rotate only 10-1 numbers 10-1 times etc. It means for first 9 results in step two:

    10 9 8 7 6 5 4 3 2 1
    10 8 7 6 5 4 3 2 1 9
    10 7 6 5 4 3 2 1 9 8
    10 6 5 4 3 2 1 9 8 7
    10 5 4 3 2 1 9 8 7 6
    ...

    etc, notice, that first line is present from previous step, so it must not be added to generated set again.

    Algorithm recursively doing exactly that, what is explained above. It is possible to generate all the 3628800 combinations for 10!, because number of nesting is the same as number of elements in array (it means in your case for 10 numbers it lingers about 5min. on my computer) and you need have enough memory if you want to keep all combinations in array.

    There is solution.

    package permutation;
    
    /** Class for generation amount of combinations (factorial)
     * !!! this is generate proper permutations without repeating and proper amount (počet) of rows !!!
     *
     * @author hariprasad
     */
    public class TestForPermutationII {
      private static final String BUMPER = "*";
      private static int counter = 0;
      private static int sumsum = 0;
      // definitoin of array for generation
      //int[] testsimple = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
      int[] testsimple = {1, 2, 3, 4, 5};
      private int ELEMNUM = testsimple.length;
      int[][] shuff;
    
      private String gaps(int len) {
        String addGap = "";
        for(int i=0; i <len; i++)
          addGap += "  ";
        return addGap;
      }
    
      /** Factorial computing */
      private int fact(int num) {
        if (num > 1) {
          return num * fact(num - 1);
        } else {
          return 1;
        }
      }
    
      /** Cyclic shift position to the left */  
      private int[] lShiftPos(int[] arr, int pos) {
        int[] work = new int[ELEMNUM];
        int offset = -1;
        for (int jj = 0; jj < arr.length; jj++) {
          if (jj < pos) {
            work[jj] = arr[jj];
          } else if (jj <= arr.length - 1) {
            if (jj == pos) {
              offset = arr[pos]; // last element
            }
            if (jj != (arr.length - 1)) {
              work[jj] = arr[jj + 1];
            } else {
              work[jj] = offset;
            }
          }
        }
        return work;
      }
    
      private String printBuff(int[] buffer) {
        String res = "";
        for (int i= 0; i < buffer.length; i++) {
          if (i == 0) 
            res += buffer[i];
          else
            res += ", " + buffer[i];
        }
        return res;
      };
    
      /** Recursive generator for arbitrary length of array */
      private String permutationGenerator(int pos, int level) {
        String ret = BUMPER;
        int templen = counter;
        int[] work = new int[ELEMNUM];
        int locsumread = 0;
        int locsumnew = 0;
        //System.out.println("\nCalled level: " + level);
    
        for (int i = 0; i <= templen; i++) {
          work = shuff[i];
          sumsum++;
          locsumread++;
          for (int ii = 0; ii < pos; ii++) {
            counter++;
            sumsum++;
            locsumnew++;
            work = lShiftPos(work, level); // deep copy
            shuff[counter] = work;
          }
        }
    
        System.out.println("locsumread, locsumnew: " + locsumread + ", " + locsumnew);
        // if level == ELEMNUM-2, it means no another shift
        if (level < ELEMNUM-2) {
          ret = permutationGenerator(pos-1, level+1);
          ret = "Level " + level + " end.";
          //System.out.println(ret);
        }
        return ret;
      }
    
      public static void main(String[] argv) {
        TestForPermutationII test = new TestForPermutationII();
        counter = 0;
        int len = test.testsimple.length;
        int[] work = new int[len];
    
        test.shuff = new int[test.fact(len)][];
    
        //initial
        test.shuff[counter] = test.testsimple;
        work = test.testsimple; // shalow copy
    
        test.shuff = new int[test.fact(len)][];
        counter = 0;
        test.shuff[counter] = test.testsimple;
        test.permutationGenerator(len-1, 0);
    
        for (int i = 0; i <= counter; i++) {
          System.out.println(test.printBuff(test.shuff[i]));
        }
    
        System.out.println("Counter, cycles: " + counter + ", " + sumsum);
      }
    }
    

    Intensity (number of cycles) of algorithm is sum of incomplete factorials of number of members. So there is overhang when partial set is again read to generate next subset, so intensity is:

    n! + n!/2! + n!/3! + ... + n!/(n-2)! + n!(n-1)!

    0 讨论(0)
提交回复
热议问题