Java para descobrir se um array é um subconjunto de outro

Nov 24 2020

Estou tendo problemas para descobrir se uma quantidade específica de números está em outra matriz. A primeira matriz gera 10 números aleatórios e na segunda matriz o usuário adivinha 5 números. Estou tentando descobrir se o usuário adivinhou alguma sequência. Usei para loops para descobrir se os números de entrada do usuário estão em qualquer um dos números de 1 a 5 na matriz de 10; caso contrário, ele verificará os números de 2 a 6 e assim por diante. Por exemplo, se o programa teve os seguintes números vencedores: 23 56 67 06 43 22 59 24 90 66 e o ​​usuário inseriu: 01 06 43 22 89. Continuo obtendo o índice fora dos limites. Como faço para corrigir isso?

    // to check if user guessed a sequence
    
    boolean guessed = false;
    int counter = 0;
    int i , j = 0;
    
    for (i = 4; i < numbers.length; i++) {    // users numbers
        
        for ( j = 4; j < lottery.length; j++) {  // first 5 numbers from array 
            
            if ( lottery[i] == numbers[j]) {
                break;
            }
            if ( j == i) {
                guessed = true;
            }
        }
    }

Respostas

1 AlexRudenko Nov 24 2020 at 20:50

Parece que um método semelhante a String::indexOfdeve ser implementado nesta tarefa para os arrays que tentam encontrar um índice de um subarray int indexOf(int[] search, int[] input).

Além disso, pode ser necessário procurar todos os submatrizes possíveis do searchsubarray ( lottery). Assim, o método mencionado deve ser estendido para procurar uma subfaixa do searchargumento:int indexOf(int[] search, int[] input)

A implementação direta seria:

static int indexOf(int search[], int from, int to, int[] input) {
    if (null == search || null == input || search.length > input.length) {
        return -1;
    }
    
    for (int i = 0, n = input.length - (to - from); i <= n; i++) {
        boolean found = true;
        for (int j = from; found && j < to; j++) {
            if (input[i + j - from] != search[j]) {
                found = false;
            }
        }
        if (found) {
            return i;
        }
    }
    return -1;
}

As larguras e índices apropriados from/ todos subintervalos de pesquisa podem ser gerados da seguinte forma (de todo o comprimento de lotteryaté 2):

int[] numbers = {23, 56, 67, 06, 43, 22, 59, 24, 90, 66};
int[] lottery = {01, 06, 43, 22, 89};

for (int n = lottery.length; n > 1; n--) {
    for (int m = 0; m <= lottery.length - n; m++) {
        int ix = indexOf(lottery, m, m + n, numbers);
        if (ix > -1) {
            System.out.printf("Found subarray %s, width=%d from: %d to %d ",
                    Arrays.toString(Arrays.copyOfRange(lottery, m, m + n)), n, m, m + n - 1);
            System.out.printf("at index: %d%n", ix);
        }
    }
}

Resultado

Found subarray [6, 43, 22], width=3 from: 1 to 3 at index: 3
Found subarray [6, 43], width=2 from: 1 to 2 at index: 3
Found subarray [43, 22], width=2 from: 2 to 3 at index: 4

Uma implementação mais eficiente usaria o algoritmo Knuth-Morris-Pratt para ignorar verificações recorrentes dos mesmos valores na matriz de entrada.