Ayuda!! agregar elementos no repetidos de un arreglo a otro

Iniciado por juankefdg, 9 Abril 2017, 05:55 AM

0 Miembros y 1 Visitante están viendo este tema.

juankefdg

Buen día, muchachos soy nuevo en esto de la programación, necesito ayuda urgente con este problema y es que le he dado vueltas y mi cabeza esta a estallar mi pregunta seria: Diseñar un método para generar un arreglo y[k] que contenga los elementos que no se repiten en x[n]:

ejemplo:

x[n]={2,8,0,2,7,8,3,4}

Tendria que imprimir:

y[k]={0,7,3,4}

el codigo que hecho es el siguiente:

Código (java) [Seleccionar]
public static void arreglo(int n, int x[],int y[])
{
int contador=0;
int i;
int j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(x[i]!=y[j])
{
contador=contador+1;
y[j]=x[i];
}

}
System.out.println("el arreglo y[k]contiene los elementos "+y[i]);
}
}

pero no he podido dar con el problema. Agradezco un ayudita. Gracias


· Los códigos deben ir en etiquetas GeSHi
>aquí las reglas del foro
-Engel Lex

Serapis

#1
Hay varias maneras, dados los números de tu array, el primer método que te describo es el más rápido, pero no vale siempre... lee bien todos los comentarios, aunque salga una respuesta larga.... e intenta entenderla entera...

Una variación del algoritmo de ordenación Counting, lo resuelve (la variación es añadir un paso de filtrado de repetidos).
Si los límites de los números son muy grandes (distantes entre sí), no interesa esta forma de resolverlo, porque exige crear un array del tamaño entre esos límites. Tampoco sirve si se usan valores fraccionarios y hay diferente número de decimales o son demasiados (si sólo son 1 o 2 podría truncarse a entero multiplicando todos por 100, y a la salida dividirlos de nuevo entre 100).

Vamos con el desarrollo en pseudocódigo, así tienes que hacer algo por tu cuenta y no lo tienes mascado y sea sólo copiar y pegar...

Declaramos las siguientes variables:
Varias de tipo numérico (k, Min, Max, n, x, ....) que actuarán como contador, índices de array, límites, etc...
dos arrays (cuenta y ValoresUnicos), el tamaño del primero se fija en el segundo paso y el otro en el 4º paso. (en este primer método que explico)

Paso1: Hallar los límites del array (valor menor y mayor)
Al término de este bucle, ya sabemos el valor mínimo y máximo del array.
min= array(0)
max = min
Iniciar bucle para k y recorrer desde 1 hasta fin del array (el elemento 0, ya se ha tratado previo al bucle)
   Si array(k) es menor que Min luego
         Min= array(k)
   en otro caso si array(k) es mayor que Max luego
        Max = array(k)
   fin si
   incrementar k
fin bucle


Paso 2: Contar la presencia de cada valor sobre un array temporal
redimensionar Array Cuenta desde min hasta max
Iniciar bucle para k y recorrer desde 0 hasta fin del array
   cuenta(Array(k)) = cuenta(Array(k)) +1
   incrementar k
fin bucle

NOTA: Muchos lenguajes no permiten declarar un array a un índice que no sea siempre 0, en este caso, hay que hacer los cambos siguientes (recordar hacer los cambios correspondientes en los siguientes pasos, si yo los olvido)

redimensionar cuenta desde 0 hasta max - min

Iniciar bucle para k y recorrer desde 0 hasta fin del array
   cuenta(Array(k)-min) = cuenta(Array(k)-min) +1
   incrementar k
fin bucle


Paso 3: recorremos cada 'jaulita', para ver cuántos 'conejos' han caído en la 'trampa':
Iniciar bucle para K recorriendo desde Min hasta Max
   Si cuenta(k) es mayor que 0 luego unicos = unicos +1
   Incrementar k
fin bucle

Recordar que si no podemos delcarar el array comenzando en el índice Min, hay que restar siempre Min a todas las referencias, así este bucle para aquellos caso quedaría como:
Iniciar bucle para K recorriendo desde 0 hasta Max - Min
   Si cuenta(k) es mayor que 0 luego
        incrementar unicos
   fin si
   Incrementar k
fin bucle


Paso 4: finalmente dado que ya conocemos cuantos conejos hemos cazado, pedimos el camión que ha de trasladarlos, del tamaño que quepan todos en su jaulita.
Esto es, ya conocemos cuantos son los valores únicos que aparecen en el array, podemos declarar un nuevo array con ese tamaño y por tanto en el siguiente bucle solo resta pasarlos al nuevo:

declarar array ValoresUnicos desde 0 hasta unicos -1
Iniciar bucle para K recorriendo desde Min hasta Max
   Si cuenta(k) es mayor que 0 luego
       ValoresUnicos(n) = (k+min)
       Incrementar n
       Si n es igual que unicos salir del bucle, ya no hay más...
   fin si
   Incrementar k
fin bucle

Devolver el array ValoresUnicos (que además estará ordenado de menor a mayor).


-----------------------------------------------------
Comentarios:

- Básicamente para lograr solucionar el problema, la primera acción es siempre ordenar el array sea por el método que sea.
- El método expuesto de ordenar más arriba es por "Counting" es el más rápido de todos los métodos de ordenar, pero tiene severas restricciones que limitan su uso asituaciones reducidas (éste es un caso claro, donde es preferible usarlo a cualquier otro método, OJO: ciendo los valores del array que muestras)...
Esas limitaciones son: solo vale para números, deben ser enteros (preferiblemente), y los límites (valor Min y Max) deben ser un tamaño manejable, por ejemplo: si hay 25 números en el array el menor es -12345678 y el mayor es +98765432, no interesa porque hay que recorrer una cantidad enorme para solo 25 valores contenidos en el array... que ha de contener, además exige una memoria extra para almacenar el tamaño de dicho array. Cuando con estos datos se decida/impida usar este algoritmo debe recurrirse a otro algoritmo que ordene el array...


- Si no interesa ordenar el array por counting, debemos ordenarlo por otro método, considerándolo entonces el paso 1 (ordenarlo en Counting es el paso 2).
Aquí expongo entonces la forma para otras opciones:


Paso 1: Tendremos entonces que ordenado el array por otro método, sabemos que Min y Max estarán en la posición 0 y última del array ordenado respectivamente, pero aquí esos valores no se precisan. Si el array es tan pequeño como el ejemplo que pones incluso el de burbuja es preferible a otros, si el cuanto mayor sea el array, tanto más relevancia tendrá que sea más rápido... el método de ordenación a usar... Se da por hecho este paso...

Paso 2: Contar los valores únicos... tendría un bucle tampoco demasiado complejo 8es el paso equivalente al 3 del método expuesto más arriba)

unicos=0
x= array(0)
Iniciar bucle para K recorriendo desde 1 hasta fin del array
    Si array(k) es distinto que X entonces
        incrementar unicos
        x = array(k)
    fin si
    Incrementar k
Fin bucle


Paso 3: Sabiendo ya la cantidad de valores únicos que tenemos en el array, podemos hacer (casi) lo mismo que hicimos en paso 4 del método anterior (algoritmo counting), pasarlos al array ValoresUnicos, pero el modo de revisión cambia ligeramente).

Declarar array ValoresUnicvos desde 0 hasta Unicos -1
x= array(0)
ValoresUnicos(0) = x

n=0
Iniciar bucle para K recorriendo desde 1 hasta fin del array
    Si array(k) es distinto que X entonces        
       x = array(k)
       incrementar n
       ValoresUnicos(n) = x
       si n es igual a unicos salir del bucle (ya se encontraron todos)
   fin si
    Incrementar k
Fin bucle

Devolver array ValoresUnicos


...y eso es todo.

Más comentarios:
- Si se conoce de antemano los valores Min y Max, el paso 1 del primer método no sería necesario.
- Si se conoce de antemano la cantidad de valor únicos, también puede omitirse el paso de contar los valores únicos en cada método... y el array a devolver puede declararse del tamaño adecuado desde un principio.
- Piensa que la solución, cualquier solución rápida pasa por ordenar o un equivalente (un método que dado un elemento repetido tenga capacidad de omitirlo). Así otra buena opción sería crear una colección de elementos únicos que no admitan repetición (una tabla hash exclusiva, por ejemplo), e ir introduciendo uno a uno en la colección y cuando falle porque el elemento ya existe, seguir con el siguiente, etc... al final los elementos que contenga la colección serán los elementos únicos no repetidos, faltaría pues volcarlos a un array si se exige la devolución sobre un array, sino devolver directamente la propia colección.
- Si se usó un método de ordenación, para luego proceder con el filtrado, el array a devolver además estará ordenado.

Quizás se me haya escapado algún pequeño gazapo al escribir.. ya lo corregirás cuando pruebes el código que realices...  

juankefdg

#2
Código (java) [Seleccionar]
[public static void arreglo(int n, int x[],int y[])
{
int unicos=0;
int cuenta[] = null;
int ValoresUnicos[] = null;
int min=x[0];
int max=min;
int contador=0;
int i,j;
    for(j=0;j<n;j++)
    {
    if(y[j]<min)
    {
    min=y[j];
    }
    j++;
    }
    for(j=0;j<n;j++)
    {
    cuenta[y[j-min]]=cuenta[y[j-min]+1];
    j++;
    }
    for(j=min;j<max;j++)
    {
    if(cuenta[j]>0)
    {
    unicos=unicos+1;
    j++;
    }
    }
    for(j=min;j<max;j++)
    {
    ValoresUnicos[n]=(j+min);
    n++;
    if(n==unicos)
    {
    }
    j++;
    }
    System.out.println(ValoresUnicos[n]);
}
}]no e entendido lo de redimensionar cuenta desde 0 hasta max-min y no se como devolver el array Valores unicos, java me envia los array Cuenta y ValoresUnicos como null

juankefdg

[public static void arreglo(int n, int x[],int y[])
{
int temp;
int contador=0;
int i,j;
    for(i=0;i<n;i++){
        temp = x[i];
        for( j=0;j<n;j++){
            if(temp == x[j]){
                contador=contador+1;
            }
        }
        if (contador==1){
           x[i]=x[j];
        }
        System.out.println(x[i]);
    }
}
}]

intente hacerlo de esta forma pero no se como retornar los valores que sean iguales a 1

Serapis

#4
No has llegado a interpretarme correctamente. Te desgrano cada bucle, porque cometes errores en todos ellos...

Antes de nada te comento el punto final...
Cita de: juankefdg en 10 Abril 2017, 05:50 AM
no he entendido lo de redimensionar cuenta desde 0 hasta max-min ... java me envia los array Cuenta y ValoresUnicos como null
Redimensionar = dimensionar = inicializar a un tamaño específico.
En java un array se inicializa a un amaño específico así:
NombreArray = new TipoDato[tamaño];
Sólo una vez que inicialices el array al tamaño deseado, estos podrán contener algo, si desde el comienzo están vacíos y siguen vaciós, al final también estarán vacíos. Inícialos, y luego ya en los bucles se irán rellenando con los valores adecuados. al iniciarlizarlos, se le da un tamaño al array (que luego puede consukltarse con: array.length) y cada valor del mismo se pone al valor 0.

Cita de: juankefdg en 10 Abril 2017, 05:50 AM
y no se como devolver el array Valores unicos,
Bueno, esto ya es falta de conocimiento del lenguaje, es algo que pudes consultar perfectamente guglenado, si no tienes un libro a mano, o una web de referencia del lenguaje Java... No tiene caso preguntar cosas que están escritas en 1.000 partes desde hace 20 años o más... De entrada si no sabes devolverlos, al menos entrégalos por referencia como parámetro en la llamada de la función... de hecho mirando tu función:
- La declaras como void (sin devolución), yo devolvería el valor de 'Unicos'.
- Tienes dos arrays declarados en la entrada de la función: int x[], int y[] ...si el array x contiene los valores entre los que deseamos buscar, qué contiene el array y?... ese array podría ser el array Valoresunicos (da igual el nombre que le pongas, pero siempre mejor si es significativo).
- Supongo que 'n' es el tamaño del array x... puedes usar para el caso x.Length y así no es preciso en la función el parámetro n.

------------------------
------------------------

Empiezo comentando tu código, para señalarte las correccioes que necesita, bucle por bucle:
Cuando recorres el bucle para encontrar el valor menor (del PASO 1) en  tú codigo, pones:
Código (java) [Seleccionar]
for(j=0;j<n;j++)
   {
    if(y[j]<min)
    {
    min=y[j];
    }
    j++;
   }

...al mismo tiempo puedes ir hallando el mayor... imagina que tienes esta corta serie de valores: 7,17,3,15,21,2,9 ...al empezar el bucle tomamos como menor y mayor el primero de la serie, el valor 7...
Luego que entramos preguntamos si el siguiente ítem y(1)< min, esto es si 17 es menor que 7, no es menor, luego si no es menor, queda que : o es igual que siete o es mayor, luego, en la alternativa (al si) se pregunta si es mayor que 7 y si es así, asignamos el valor a mayor (si resulta serlo).
En definitiva nos basta un solo bucle para encontrar el menor y también el mayor de la serie.
Es más, es que no veo que busques el mayor de la serie, creí que lo hacías en otro bucle aparte más adelante..., pero mirando resulta que no, que te has olvidado de ello.

   Si array(k) es menor que Min luego
         Min= array(k)
  [b] en otro caso[/b]  (lo desmonto en otra línea para que te quede más claro...)
        [b]si array(k) es mayor que Max luego
            Max = array(k)
        fin si[/b]
   fin si

Si no buscas el mayor, entonces el valor que usar más adelante para mayor, es que usamos al comienzo, el contenido del indice 0.

De igual modo, aunque de menor importancia, puesto que el primer elemento de la serie ya lo hemos asignado de entrada como el menor y el mayor, el bucle puede ser iniciado desde el siguiente elemtno, es decir el 1 y no volver al cero como haces en: "for(j=0", si hemos asignado ese valor ya, al preguntar 7 no será menor que 7, y 7 tampoco será mayor que 7.... pero bueno, es solo un ítem por el que s epregunta, no tiene más importancia. Tu deberías poner: "for(j=1"


Ahora vamos a repasar el bucle del PASO-2:
Cita de: juankefdg en 10 Abril 2017, 05:50 AM
Código (java) [Seleccionar]

for(j=0;j<n;j++)
   {
    cuenta[y[j-min]]=cuenta[y[j-min]+1];
    j++;
   }
De entrada el array cuenta, aunque está declarado, no está inicializado, no se le ha asignado un tamaño. En Java, no se permite empezar en otro índice que no sea 0, así que el array debería desde 0 hasta Max-Min. Una vez redimensionado el array (inicializado, quizás te suene
En el código que pones para el segundo paso, no lo has interpretado correctamente ...
Yo puse:
redimensionar cuenta desde 0 hasta max - min
Iniciar bucle para k y recorrer desde 0 hasta fin del array
   cuenta(Array(k)-min) = cuenta(Array(k)-min) +1
   incrementar k
fin bucle

Fíjate en lo que tu pones: cuenta[y[j-min]]
Y lo que yo te puse: cuenta(Array(k)-min)
Y no me refiero a las llaves y paréntesis (obviamente), si no a donde está el signo '-' y por tanto de qué se hace la resta... es decir no hacemos resta del índice, sino del valor que contiene ese índice.,... si te fijas, tu tienes 2 cierres de llave al final, yo solo 1, por que el otro cierre, el del índice está tras el índice mismo.

Ahora repaso el código del bucle del PASO-3, hay dos fallos, donde tu tienes:
Cita de: juankefdg en 10 Abril 2017, 05:50 AM
Código (java) [Seleccionar]
for(j=min;j<max;j++)
   {
    if(cuenta[j]>0)
    {
    unicos=unicos+1;
    j++;
    }
   }

El código es casi correcto, pero contiene 2 fallos:
El primero está en la declaración del bucle, tu has puesto en tu código: for(j=min;j<max;j++)
Y yo puse: Iniciar bucle para K recorriendo desde 0 hasta Max - Min
Luego lo correcto sería poner: for(j=0;j<(max-min);j++)

El otro error lo cometes bucle tras bucle...
Verás cuando yo estructuro un bucle en pseudocódigo:
Iniciar bucle para x desde y hasta z
   ...
  [b] Incrementar X[/b]
fin bucle

El punto de incrementar, es dependiente de qué tipo de bucle se use, si se usa un bucle for... ya lleva en el propio código, como se incrementa. ...en Java igual que en C, (señalado en negrita) es en la forma: for(x=y;x<z;x++)
Luego no hace falta que al finalizar el bucle vuelvas a incrementar el valor de la variable de control del bucle, porque entonces estás saltando en cada ciclo 2 unidades cada vez.
El 'incrementar x', debe interpretarse que es así, pero si el formato del bucle ya lo ofrece por sí mismo, ya está, no hay que añadirlo. ...pero en bucles de tipo While... no se 'autoincrementa' en el diseño del bucle de forma automática, luego ahí si sería preciso explicitarlo. En TODOS los bucles for que has puesto, por tanto están sobrando...

Por fin te comento el cuarto bucle de tu código, correspondiente al paso 4:
Cita de: juankefdg en 10 Abril 2017, 05:50 AM
Código (java) [Seleccionar]
for(j=min;j<max;j++)
   {
    ValoresUnicos[n]=(j+min);
    n++;
    if(n==unicos)
    {
    }
    j++;
   }


De entrada no has inicializado el array ValoresUnicos (arriba del todo te comentaba si ese array podría ser el mismo que el array 'y', que entra en la función.

Luego la declaración del bucle, tampoco es correcta. Supongo que el error es porque no has trasladado mi declaración al caso de Java. En Java los arrays siempre empiezan en el índice 0, entonces debes hacer el cambio preciso.
Si yo puse esto: Iniciar bucle para K recorriendo desde Min hasta Max
Usando Java deberías poner: for(j=0;j<cuenta.length-1;j++)

el resto del bucle, también está muy desorientado:
Si o puse, en el cuerpo del bucle:
  Si cuenta(k) es mayor que 0 luego
       ValoresUnicos(n) = (k+min)
       Incrementar n
       Si n es igual que unicos salir del bucle, ya no hay más...
   fin si

tu deberías poner:
Código (java) [Seleccionar]
if(cuenta[j]>0){
   ValoresUnicos[n]=(j+min);
   n++;
}

Solo dos cosas más... dado que la variable 'n', tu ya la traes con un valor en la entrada de la función, tienes que hacer una de dos cosas, o bien la pones a 0 antes del bucle, o bien creas una nueva variable que sirva de contador... en cualquier caso, no puedes usar una variable ya existente con un valor que tenga, tal cual... puedes reutilizar una variable muchas veces, pero poniendo a 0 su valor cuando antes de usarlo para otra cosa (a 0 o al valor inicial que debeiera tener, por supuesto).

Finalmente, puedes ignorar la línea: "Si n es igual que unicos salir del bucle", es sólo un ahorro para no recorrer todo el bucle si ya se asignaron todos los valores únicos. No es imprescindible, y probablemente no suponga una mejora en velocidad salvo que a priori se sepa por ejemplo, que hay 1 millón de elementos, pero sólo haya 5 únicos y que estén todos al principio... Este detalle si quieres lo pones en el código, pero lo dejas comentado, cuando tengas más conocimiento del lenguaje y sobreprogamar, lo entenderás claro.

p.d.: Tu último mensaje no lo comento. En este aún con tantos errores tiene mejor enfoque que aquél, que tienes bucles anidados...

cunian


try {
        txtresultado.setText("");
        String dato = txtnum.getText().trim();
        String r = "";
        int cc = 0;
        for (int i = 0; i < dato.length(); i++) {
            for (int c = 0; c < dato.length(); c++) {
                if (dato.charAt(i) == dato.charAt(c)) {
                    cc++;
                }
            }
            if (cc >= 2) {
                //EVALUO NUMEROS REPETIDOS
                r = r + dato.charAt(i);
            }
            cc = 0;
        }
        //CREO VECTOR PARA GUARDAR LOS VALORES
        String vrepetidos[] = new String[r.length()];
        for (int i = 0; i < r.length(); i++) {
            vrepetidos[i] = r.charAt(i) + "";
        }

        for (int i = 0; i < vrepetidos.length; i++) {
            for (int j = 0; j < vrepetidos.length - 1; j++) {
                if (i != j) {
                    //EVALUO  QUE POSICIONES SON IGUALES Y EN UNA POCICION LLENO CON ESPACIO
                    if (vrepetidos[i] == null ? vrepetidos[j] == null : vrepetidos[i].equals(vrepetidos[j])) {
                        vrepetidos[i] = "";
                    }
                }
            }
        }

        int t = vrepetidos.length;
        //IMPRIMO LAS POCICIONES QUE NO TENGAN ESPACIO
        for (int k = 0; k <= t - 1; k++) {
            if (!"".equals(vrepetidos[k])) {
                txtresultado.setText(txtresultado.getText() + " " + vrepetidos[k]);
            }
        }
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "INGRESE DATOS");
        }

Serapis

#6
Cita de: cunian en 17 Abril 2017, 03:44 AM


       for (int i = 0; i < dato.length(); i++) {
           for (int c = 0; c < dato.length(); c++) {

: NO POR DIOS, NO... BUCLES ANIDADOS aquí NO.              
         
No se te ocurra hacer una mala implementación como la antepuesta.
- Usa en dos ocasiones un bucle anidado... lo que implica que el tiempo es n² + ... + x^2 + ..., siendo x el número de repetidos más de una vez (ni siquiera el de únicos, omite los que sólo aparecen una vez.)
- Lo que yo te propuse requiere: n + 3m.
Siendo n el tamaño del array de entrada y 'm' el array generado (entre el valor min y max).

Claramente si tienes un array de 100 elementos, donde el valor menor es 10 y el mayor 200:
-- Bien implementado conlleva: 100 + 3*190 ciclos. = 670ciclos.
-- Con la implementación pésima conlleva: 100² + 100 + x² + 100= 20.200ciclos.
Para pequeños arrays (de hata 20 ítems, da igual), pero consideremos ahora un array de bytes de un tamaño de 1millón de ítems.
- Bien implementado: 1.000.000 + 3*256 = 1.000.784 ciclos.(1millón)
- Mal implementado: 1.000.000² + 256 + 256² + 256 = 1.000.000.066.048 de ciclos (1billón)

Si el array tiene límites muy distantes entre sí, es preferible usar otro método de ordenar (no uno de burbuja, por supuesto), pero una vez ordenado, el resto sigue siendo lo mismo, tal como comentaba en un mensaje previo.
Aquí el usuario cunian, sigue el esquema parecido al que muestro pero procediendo básicamente con el algoritmo de burbuja (de forma subyacente), que como todo quisque que sepa algo de programar sabe que no debe usar nunca, salvo para aprendizaje... aparte realiza mucho trasiego de cadenas innecesario...

Ni punto de comparación...