web-dev-qa-db-fra.com

Imprimer toutes les permutations d'un tableau

Je travaille sur un programme et une fonction qui permute les positions dans un tableau de longueur entrée par un utilisateur. Cependant, j'essaie de comprendre comment imprimer cet appel de fonction N! fois, qui énumérerait toutes les permutations dans la fonction.

Mon code pour la fonction de permutation est:

static void nextPerm(int[] A){
    for( int i = (n-1); i > 0; i-- ){
        if( A[i] < A[i+1] ){
            A[i] = pivot;
            continue;
        }
        if( A[i] >= A[i+1] ){
            reverseArray(A);
            return;
        }
    }

    for( int i = n; i > 0; i--){
        if( A[i] > pivot ){
            A[i] = successor;
            continue;
        }
    }

    Swap(pivot, successor);

    int[] B = new int[pivot+1];
    reverseArray(B);

    return;
}

Dois-je écrire une boucle dans la fonction main, cela affichera ceci n! fois?

11
user4309460

Créer (ou imprimer) les permutations d'un tableau est beaucoup plus facile en combinant de manière récursive et itérative que purement itérative. Il y a sûrement des façons itératives de le faire, mais c'est particulièrement simple avec une combinaison. Plus précisément, notez qu'il existe par définition N! permutations d'une longueur N tableau - N choix pour le premier emplacement, N-1 choix pour le 2e, etc. etc. Ainsi, nous pouvons décomposer un algorithme en deux étapes pour chaque indice i du tableau .

  1. Sélectionnez un élément dans le sous-tableau arr[i....end] pour qu'il soit l'élément ith du tableau. Échangez cet élément avec l'élément actuellement à arr[i].
  2. Permute récursivement arr[i+1...end].

Nous notons que cela se passera dans O (N!), Comme lors du premier appel, N sous appels seront effectués, chacun effectuant N-1 sous appels, etc. , et tant que seuls les échanges sont faits, aucun élément ne sera jamais dupliqué.

public static void permute(int[] arr){
    permuteHelper(arr, 0);
}

private static void permuteHelper(int[] arr, int index){
    if(index >= arr.length - 1){ //If we are at the last element - nothing left to permute
        //System.out.println(Arrays.toString(arr));
        //Print the array
        System.out.print("[");
        for(int i = 0; i < arr.length - 1; i++){
            System.out.print(arr[i] + ", ");
        }
        if(arr.length > 0) 
            System.out.print(arr[arr.length - 1]);
        System.out.println("]");
        return;
    }

    for(int i = index; i < arr.length; i++){ //For each index in the sub array arr[index...end]

        //Swap the elements at indices index and i
        int t = arr[index];
        arr[index] = arr[i];
        arr[i] = t;

        //Recurse on the sub array arr[index+1...end]
        permuteHelper(arr, index+1);

        //Swap the elements back
        t = arr[index];
        arr[index] = arr[i];
        arr[i] = t;
    }
}

Exemple d'entrée, sortie:

public static void main(String[] args) {
    permute(new int[]{1,2,3,4});
}

[1, 2, 3, 4]
[1, 2, 4, 3]
[1, 3, 2, 4]
[1, 3, 4, 2]
[1, 4, 3, 2]
[1, 4, 2, 3]
[2, 1, 3, 4]
[2, 1, 4, 3]
[2, 3, 1, 4]
[2, 3, 4, 1]
[2, 4, 3, 1]
[2, 4, 1, 3]
[3, 2, 1, 4]
[3, 2, 4, 1]
[3, 1, 2, 4]
[3, 1, 4, 2]
[3, 4, 1, 2]
[3, 4, 2, 1]
[4, 2, 3, 1]
[4, 2, 1, 3]
[4, 3, 2, 1]
[4, 3, 1, 2]
[4, 1, 3, 2]
[4, 1, 2, 3]
15
Mshnik

J'ai suivi cette méthode la plupart du temps. (Il est donné par Robert Sedgewick et Kevin Wayne.).

public class Permutations {

    // print N! permutation of the characters of the string s (in order)
    public  static void perm1(String s) { perm1("", s); }
    private static void perm1(String prefix, String s) {
        int N = s.length();
        if (N == 0) System.out.println(prefix);
        else {
            for (int i = 0; i < N; i++)
               perm1(prefix + s.charAt(i), s.substring(0, i) + s.substring(i+1, N));
        }

    }

    // print N! permutation of the elements of array a (not in order)
    public static void perm2(String s) {
       int N = s.length();
       char[] a = new char[N];
       for (int i = 0; i < N; i++)
           a[i] = s.charAt(i);
       perm2(a, N);
    }

    private static void perm2(char[] a, int n) {
        if (n == 1) {
            System.out.println(a);
            return;
        }
        for (int i = 0; i < n; i++) {
            swap(a, i, n-1);
            perm2(a, n-1);
            swap(a, i, n-1);
        }
    }  

    // swap the characters at indices i and j
    private static void swap(char[] a, int i, int j) {
        char c;
        c = a[i]; a[i] = a[j]; a[j] = c;
    }

Cependant, il existe aussi un moyen plus simple de le faire. Peut-être pouvez-vous aussi travailler autour de cela 

class PermutingArray {
    static void permutingArray(Java.util.List<Integer> arrayList, int element) {
        for (int i = element; i < arrayList.size(); i++) {
            Java.util.Collections.swap(arrayList, i, element);
            permutingArray(arrayList, element + 1);
            Java.util.Collections.swap(arrayList, element, i);
        }
        if (element == arrayList.size() - 1) {
            System.out.println(Java.util.Arrays.toString(arrayList.toArray()));
        }
    }

    public static void main(String[] args) {
        PermutingArray
                .permutingArray(Java.util.Arrays.asList(9, 8, 7, 6, 4), 0);
    }
}

Exemple de travail ici .. IDeone Link

6
Ankur Anand

L'astuce consiste à renvoyer une valeur spéciale (false dans le code ci-dessous) de nextPerm quand il s'agissait de la dernière permutation (c'est-à-dire lorsque le tableau est trié par ordre décroissant):

import Java.util.*;

public class Main {
    public static boolean nextPerm(List<Integer> a) {
        int i = a.size() - 2;
        while (i >= 0 && a.get(i) >= a.get(i + 1))
            i--;

        if (i < 0)
            return false;

        int j = a.size() - 1;
        while (a.get(i) >= a.get(j))
            j--;

        Collections.swap(a, i, j);
        Collections.reverse(a.subList(i + 1, a.size()));
        return true;
    }
    ...

Ensuite, vous pouvez utiliser la boucle (notez que le tableau requis doit être trié par ordre croissant initialement):

    ...
    public static void main(String[] args) {
        List<Integer> a = Arrays.asList(new Integer[] {1, 2, 3, 4});
        do {
            System.out.println(a);
        } while (nextPerm(a));
    }
}

Vous pouvez essayer ce code ici: http://ideone.com/URDFsc

0
dened