Question

Je dois générer toutes les variantes sans répétitions en chiffres 0 - 9.

Longueur d'entre eux pourrait être de 1 à 10. Je ne sais vraiment pas comment le résoudre, en particulier comment éviter les répétitions.

Exemple:    longueur de variations: 4    variations aléatoires: 9856, 8753, 1243, 1234, etc. (mais pas 9985 - contient la répétition)

Je serais vraiment reconnaissant si quelqu'un peut me aider avec cette question, en particulier de donner un code et des indices.

Était-ce utile?

La solution

Le mot-clé à rechercher est permutation . Il y a une abondance de code source librement disponible qui les exécute.

Quant à garder la répétition libre, je suggère une approche récursive simple: pour chaque chiffre que vous avez le choix de le prendre dans votre variation ou non, de sorte que votre récursion compte par les chiffres et les fourchettes en deux appels récursifs, un dans lequel le chiffre est inclus, une dans laquelle elle est exclue. Puis, après avoir atteint le dernier chiffre chaque récursion vous donne essentiellement une (unique, triés) liste des chiffres sans répétition. Vous pouvez ensuite créer toutes les permutations possibles de cette liste et de combiner toutes ces permutations pour obtenir votre résultat final.

(Comme duffymo dit: Je ne vais pas fournir le code pour cela)

Note avancée: la récursion est basée sur 0/1 (exclusion, inclusion) qui peut être directement traduit en bits, par conséquent, des nombres entiers. Par conséquent, afin d'obtenir toutes les combinaisons possibles de chiffres sans réellement effectuer la récursion lui-même, vous pouvez simplement utiliser tous les nombres entiers 10 bits et itérer à travers eux. interpréter ensuite les nombres tels qu'un bit de jeu correspond à inclure le chiffre dans la liste qui doit être permuté.

Autres conseils

Voici mon code Java. Ne hésitez pas à demander si vous ne comprenez pas. Le point principal est ici:

  
      
  1. trier à nouveau tableau de caractères. par exemple: a1 a2 a3 b1 b2 b3 .... (a1 = a2 = a3)
  2.   
  3. générer permutation et toujours garder l'état: indice de a1   
import java.util.Arrays;

public class PermutationDup {

    public void permutation(String s) {
        char[] original = s.toCharArray();
        Arrays.sort(original);
        char[] clone = new char[s.length()];
        boolean[] mark = new boolean[s.length()];
        Arrays.fill(mark, false);
        permute(original, clone, mark, 0, s.length());
    }

    private void permute(char[] original, char[] clone, boolean[] mark, int length, int n) {
        if (length == n) {
            System.out.println(clone);
            return;
        }

        for (int i = 0; i < n; i++) {
            if (mark[i] == true) continue;
            // dont use this state. to keep order of duplicate character
            if (i > 0 && original[i] == original[i-1] && mark[i-1] == false) continue;
            mark[i] = true;
            clone[length] = original[i];
            permute(original, clone, mark, length+1, n);
            mark[i] = false;
        }

    }

    public static void main(String[] args) {
        PermutationDup p = new PermutationDup();
        p.permutation("abcab");
    }
}

J'ai créé le code suivant pour générer des permutations où la commande est importante et sans répétition. Il utilise des médicaments génériques pour permutant tout type d'objet:

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;
    }
}

Imaginez que vous aviez une fonction magique - donné un tableau de chiffres, il vous renvoie les permutations correctes.

Comment pouvez-vous utiliser cette fonction pour produire une nouvelle liste de permutations avec un seul chiffre supplémentaire?

par ex.,

si je vous ai donné une fonction appelée permute_three(char[3] digits), et je vous dis que cela ne fonctionne que pour 0 chiffres, 1, 2, comment pouvez-vous écrire une fonction qui peut permute 0, 1, 2, 3, en utilisant la fonction permute_three donnée ?

...

une fois que vous avez résolu que, que remarquez-vous? pouvez-vous généraliser?

Dollar est 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));
    }
}

Le code pour ce qui est similaire à celui sans doublons, avec l'ajout d'un if-else statement.Check cette

Permutation sans répétition est basée sur le théorème, que nombre de résultats est factoriel nombre d'éléments (dans ce nombre de cas). Dans votre cas 10! est 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 = 3628800. La preuve est exactement pourquoi il est juste solution pour la production aussi. Eh bien oui, comment. En première position-à-dire de gauche, vous pouvez avoir 10 numéros, sur la deuxième position, vous pouvez avoir seulement 9 chiffres, car un seul numéro est sur la position à gauche et nous ne pouvons pas répéter le même nombre, etc. (la preuve se fait par induction mathématique ). Alors, comment générer des dix premiers résultats? Selon mes connaissances, il est plus simple d'utiliser décalage cyclique. Cela signifie que l'ordre de changement de numéro à gauche sur une position (ou à droite si vous voulez) et le nombre qui débordent de mettre sur la place vide. Cela signifie dix premiers résultats:

  

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
  ...

La première ligne est l'échantillon de base, il est donc la bonne idée de mettre en avant la génération mis. L'avantage est que, dans l'étape suivante, vous devrez résoudre le même problème pour éviter des doubles emplois indésirables.

A l'étape suivante Faire tourner récursive seulement 10-1 numéros 10-1 fois etc. Cela signifie que pour les 9 premiers résultats à l'étape deux:

  

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 8 7 9
  10 5 4 3 2 1 9 8 7 6
  ...

etc, avis, cette première ligne est présent à l'étape précédente, de sorte qu'il ne doit pas être ajouté à nouveau généré fixé.

algorithme récursif faire exactement cela, ce qui est expliqué ci-dessus. Il est possible de générer toutes les combinaisons 3628800 pour 10 !, car le nombre d'imbrication est le même que le nombre d'éléments dans le tableau (cela signifie dans votre cas pour 10 numéros, il s'attarde environ 5 minutes. Sur mon ordinateur) et vous devez avoir suffisamment de mémoire si vous voulez garder toutes les combinaisons dans le tableau.

Il est la 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);
  }
}

Intensité (nombre de cycles) de l'algorithme est la somme des factorielles incomplètes du nombre de membres. Donc, il est faux quand ensemble partiel est à nouveau lu pour générer sous-ensemble suivant, si l'intensité est:

  

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

Il y a une solution qui ne soit pas de la mienne, mais il est très agréable et sophistiqué.

    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);
        }

    }
}

Je pense que, c'est l'excellente solution.

indexation Brève permutation des connaissances utiles

Insérer un procédé qui génère la permutation correcte, étant donné une valeur d'indice entre 0 et N {! -1} pour « zéro indexé » ou {1 et N!} Pour « une indexation ».

Créer une seconde méthode contenant une « boucle », où la limite inférieure est 1 et la limite supérieure est N !. ex .. "(i; i <= N !; i ++)" pour chaque instance de la boucle appeler le premier procédé, i passant comme argument

scroll top