Permutações de uma matriz em Java

Permutações de uma matriz em Java

1. Introdução

Neste artigo, veremos como criar permutações de uma matriz.

Primeiro, vamos definir o que é uma permutação. Em segundo lugar, veremos algumas restrições. E terceiro,we’ll look at three ways to calculate them: recursively, iteratively, and randomly.

Vamos nos concentrar na implementação em Java e, portanto, não entraremos em muitos detalhes matemáticos.

2. O que é uma permutação?

A permutação de um conjunto é um rearranjo de seus elementos. Um conjunto que consiste em elementosn tem permutaçõesn!. Aquin! é o fatorial, que é o produto de todos os inteiros positivos menores ou iguais an.

2.1. Exemplo

A matriz de números inteiros [3,4,7] possui três elementos e seis permutações:

n! = 3! = 1 x 2 x 3 = 6

Permutações: [3,4,7]; [3,7,4]; [4,7,3]; [4,3,7]; [7,3,4]; [7,4,3]

2.2. Restrições

O número de permutação aumenta rapidamente comn. Embora leve apenas alguns segundos para gerar todas as permutações de dez elementos, levará duas semanas para gerar todas as permutações de 15 elementos:

image

3. Algoritmos

3.1. Algoritmo Recursivo

O primeiro algoritmo que examinamos éHeap’s algorithm. It’s a recursive algorithm which produces all permutations by swapping one element per iteration.

A matriz de entrada será modificada. Se não quisermos isso, precisamos criar uma cópia do array antes de chamar o método:

public static  void printAllRecursive(
  int n, T[] elements, char delimiter) {

    if(n == 1) {
        printArray(elements, delimiter);
    } else {
        for(int i = 0; i < n-1; i++) {
            printAllRecursive(n - 1, elements, delimiter);
            if(n % 2 == 0) {
                swap(elements, i, n-1);
            } else {
                swap(elements, 0, n-1);
            }
        }
        printAllRecursive(n - 1, elements, delimiter);
    }
}

O método usa dois métodos auxiliares:

private void swap(T[] input, int a, int b) {
    T tmp = input[a];
    input[a] = input[b];
    input[b] = tmp;
}
private void printArray(T[] input) {
    System.out.print('\n');
    for(int i = 0; i < input.length; i++) {
        System.out.print(input[i]);
    }
}

Aqui, escrevemos o resultado emSystem.out; no entanto, podemos facilmente armazenar o resultado em uma matriz ou em uma lista.

3.2. Algoritmo Iterativo

O algoritmo do Heap também pode ser implementado usando iterações:

int[] indexes = new int[n];
int[] indexes = new int[n];
for (int i = 0; i < n; i++) {
    indexes[i] = 0;
}

printArray(elements, delimiter);

int i = 0;
while (i < n) {
    if (indexes[i] < i) {
        swap(elements, i % 2 == 0 ?  0: indexes[i], i);
        printArray(elements, delimiter);
        indexes[i]++;
        i = 0;
    }
    else {
        indexes[i] = 0;
        i++;
    }
}

3.3. Permutações em ordem lexicográfica

Se os elementos forem comparáveis, podemos gerarpermutations sorted by the natural order dos elementos:

public static > void printAllOrdered(
  T[] elements, char delimiter) {

    Arrays.sort(elements);
    boolean hasNext = true;

    while(hasNext) {
        printArray(elements, delimiter);
        int k = 0, l = 0;
        hasNext = false;
        for (int i = elements.length - 1; i > 0; i--) {
            if (elements[i].compareTo(elements[i - 1]) > 0) {
                k = i - 1;
                hasNext = true;
                break;
            }
        }

        for (int i = elements.length - 1; i > k; i--) {
            if (elements[i].compareTo(elements[k]) > 0) {
                l = i;
                break;
            }
        }

        swap(elements, k, l);
        Collections.reverse(Arrays.asList(elements).subList(k + 1, elements.length));
    }
}

Este algoritmo tem uma operaçãoreverse em cada iteração e, portanto, é menos eficiente em matrizes do que o algoritmo de Heap.

3.4. Algoritmo Aleatório

Sen for grande, podemosgenerate a random permutation embaralhando a matriz:

Collections.shuffle(Arrays.asList(elements));

Podemos fazer isso várias vezes para gerar uma amostra de permutações.

Podemos criar as mesmas permutações mais de uma vez, no entanto, para grandes valores den, as chances de gerar a mesma permutação duas vezes são baixas.

4. Conclusão

Existem muitas maneiras de gerar todas as permutações de uma matriz. Neste artigo, vimos o algoritmo de Heap recursivo e iterativo e como gerar uma lista classificada de permutações.

Não é viável gerar todas as permutações para grandes matrizes, portanto, podemos gerar permutações aleatórias.

A implementação de todos os trechos de código neste artigo pode ser encontrada em nossoGithub repository.