Tengo una matriz y mi objetivo es devolver elementos únicos. Escribí el código que ordena una matriz y almacena elementos únicos en ArrayList, pero en lugar de devolver solo [7], devuelve [2,5,7]. ¿Porque?

public static void main(String[] args) {
    ArrayList<Integer> list = new ArrayList<>();
    int [] arr = {2, 5, 14, 14, 2, 7, 5};
    Arrays.sort(arr);
    for (int i =0; i<arr.length-1; i++){
        if(arr[i]!=arr[i+1]){
            list.add(arr[i]);
        }
    }
    System.out.println(list);
}
0
JohnPix 11 jul. 2021 a las 20:49

8 respuestas

La mejor respuesta

Si tiene permitido usar un mapa de frecuencia, tal vez pueda intentar construir un mapa de frecuencia de todos los valores en la matriz y luego iterar las entradas del mapa y agregar todos los elementos con valor == 1:

// A map with key as array digit and value as it's frequency
Map<Integer, Integer> frequencyMap = new HashMap<>();
ArrayList<Integer> list = new ArrayList<>();
int [] arr = {2, 5, 14, 14, 2, 7, 5};

// Build Frequency Map
for (int j : arr)
    frequencyMap.merge(j, 1, Integer::sum);

// Add all items with frequency = 1 to list
for (Map.Entry<Integer, Integer> intToFrequency : frequencyMap.entrySet()) {
    if (intToFrequency.getValue() == 1) {
        list.add(intToFrequency.getKey());
    }
}
System.out.println(list);
0
Rohan Kumar 11 jul. 2021 a las 18:07

Sugeriría usar una matriz para almacenar la frecuencia de cada elemento en la matriz y agregar aquellos elementos cuya frecuencia es 1 (elementos únicos) al list.

int max = Arrays.stream(arr).max().getAsInt();
int [] freq = new int[max+1];
for (int i=0; i<arr.length; i++)
    ++freq[ arr[i] ];
for (int e : arr)
    if (freq[ e ] == 1)
        list.add( e );
System.out.println(list);

Tenga en cuenta que esto solo funcionará cuando max no sea muy grande (<10 ^ 8). Si la matriz contiene valores más grandes, puede usar un HashMap de manera similar para almacenar las frecuencias.

1
GURU Shreyansh 11 jul. 2021 a las 18:08

Porque cuando clasifica la matriz original obtendrá {2,2,5,5,7,14} y está comparando elementos adyacentes, por lo que en la primera iteración está comparando 2 y 2 es decir, elementos en el índice 0 y 1, y dado que son iguales, no agregará el elemento en el índice 0 en la lista resultante, pero luego en la segunda iteración está comparando 2 y 5 (elemento en positon 1 y 2) y dado que no son iguales, 2 se agregará a la lista resultante. No hay necesidad de hacerlo así, simplemente puede crear Set<Integer> result desde arr y dado que Set no permite elementos duplicados, su problema está resuelto. Entonces puedes escribir algo como esto:

Set<Integer> result = new HashSet<Integer>(Arrays.asList(arr))
1
Nemanja 11 jul. 2021 a las 18:34

Cuando ordena su matriz obtiene [2,2,5,5,7,14,14]. En su bucle for, solo verifica si el elemento posterior es diferente. Cuando i = 1, arr [1]! = Arr [2] por lo tanto arr [1] se agrega aunque 2 no es un elemento único. En su lugar, compruebe si el valor anterior y posterior es diferente. Puede que tenga que cambiar la indexación en su bucle for.

Una alternativa es que puede crear un conjunto que solo almacene valores únicos. Y recorre la matriz una vez agregando cada valor al conjunto. El conjunto almacenará todos los valores únicos. A continuación, puede convertir el conjunto en una ArrayList si su método debe devolver y ArrayList.

0
Kiran Manicka 11 jul. 2021 a las 17:57

Si coloca cada número en la matriz en 2 pares diferentes, debe cambiar los índices en la instrucción if en el ciclo para que cada valor en la matriz sea parte de 1 par.

0
rozem 11 jul. 2021 a las 18:02

Tienes la idea correcta, pero complicarla demasiado.

Es mucho más fácil crear un diccionario / mapa hash y, mientras itera sobre su matriz, si el valor no está en su mapa hash, guárdelo.

Usamos un diccionario / mapa hash, porque nos proporciona un tiempo de búsqueda constante.

Al final de la iteración, su diccionario / mapa hash contendrá todos sus valores únicos en la matriz.

0
alex067 11 jul. 2021 a las 18:40

El código existente para detectar valores duplicados en una matriz ordenada debe cambiarse ligeramente para omitir los valores duplicados con la ayuda de una bandera booleana y un bucle anidado:

public static List<Integer> getUnique(int ... arr) {
    List<Integer> list = new ArrayList<>(); 
    
    System.out.print("Input: " + Arrays.toString(arr) + " -> ");

    Arrays.sort(arr);
    
    for (int i = 0, j = 0; i < arr.length; i++) {
        boolean dupFound = false;
        for (j = i + 1; j < arr.length && arr[i] == arr[j]; j++) {
            dupFound = true;
            i = j;
        }
        if (dupFound) {
            continue;
        }
        list.add(arr[i]);
    }
    return list;
}

Pruebas:

System.out.println(getUnique(2, 5, 14, 14, 2, 7, 5));
System.out.println(getUnique(2, 5, 14, 14, 20, 7, 7, 5, 14));

Salida:

Input: [2, 5, 14, 14, 2, 7, 5] -> [7]
Input: [2, 5, 14, 14, 20, 7, 7, 5, 14] -> [2, 20]

Si se le permite usar Set, esta tarea se puede resolver sin ordenar previamente la matriz de entrada y usar dos conjuntos: uno para rastrear valores distintos y el otro para rastrear valores únicos basados ​​en el hecho de que Set::add devuelve verdadero si el elemento no se ha incluido en el conjunto y false si hay un duplicado en el conjunto:

public static Set<Integer> getUnique(int ... arr) {
    Set<Integer> distinct = new HashSet<>();
    Set<Integer> unique = new HashSet<>();
    
    System.out.print("Input: " + Arrays.toString(arr) + " -> ");
    
    for (int x : arr) {
        if (distinct.add(x)) { // no duplicate found yet
            unique.add(x);     // count as unique
        } else {
            unique.remove(x);  // remove a duplicate
        }
    }
    return unique;
}

Las pruebas y sus resultados son los mismos que se muestran arriba.

0
Alex Rudenko 11 jul. 2021 a las 19:52

Si desea calcular solo con una lista y limitarse a lo básico, puede intentar lo siguiente.

public static void main(String[] args)
{
    int aux = Integer.MIN_VALUE;
    ArrayList<Integer> list = new ArrayList<>();
    int [] arr = {2, 5, 14, 14, 2, 7, 5};
    Arrays.sort(arr);
    for (int i =0; i<arr.length; i++){
        if(list.isEmpty())
        {
            //add as it is and if duplicate remove
            list.add(arr[i]);
            aux=list.get(list.size()-1);
        }
        else
        {
            if(aux == arr[i])
            {
                //check last and remove if more then 1
                if(!list.isEmpty() && list.get(list.size()-1).equals(aux))
                {
                    list.remove(list.size()-1);
                }
            }
            else
            {
                //add new
                list.add(arr[i]);
                aux=list.get(list.size()-1);
                
            }
        }
    }
    System.out.println(list);
}
0
Traian GEICU 11 jul. 2021 a las 19:15