veces una repite repetidos para numeros numero mostrar lista funcion eliminar elementos cuantas arreglo array algoritmo c++ c algorithm

una - funcion eliminar en c++



Encontrar duplicados en O(n) tiempo y O(1) espacio (12)

Algoritmo se puede ver fácilmente en la siguiente función C. La recuperación de la matriz original, aunque no es necesaria, será posible tomando cada módulo de entrada n .

void print_repeats(unsigned a[], unsigned n) { unsigned i, _2n = 2*n; for(i = 0; i < n; ++i) if(a[a[i] % n] < _2n) a[a[i] % n] += n; for(i = 0; i < n; ++i) if(a[i] >= _2n) printf("%u ", i); putchar(''/n''); }

Ideone Link para probar.

Entrada: dada una matriz de n elementos que contiene elementos de 0 a n-1, con cualquiera de estos números apareciendo cualquier cantidad de veces.

Objetivo: encontrar estos números que se repiten en O (n) y usar solo espacio de memoria constante.

Por ejemplo, supongamos que n sea 7 y array sea {1, 2, 3, 1, 3, 0, 6}, la respuesta debería ser 1 y 3. Comprobé preguntas similares aquí, pero las respuestas usaron algunas estructuras de datos como HashSet etc.

Algún algoritmo eficiente para el mismo?


Aquí está el pseudocódigo

for i <- 0 to n-1: if (A[abs(A[i])]) >= 0 : (A[abs(A[i])]) = -(A[abs(A[i])]) else print i end for

Código de muestra en C ++


Aquí está la solución:

using namespace std; sort(vec.begin(),vec.end()); for(int i = 1; i<static_cas<int>(vec.size()); i++){ if(vec[i] == vec[i-1]) cout<<vec[i]<<" "; }


Esto es lo que se me ocurrió, que no requiere el bit de signo adicional:

for i := 0 to n - 1 while A[A[i]] != A[i] swap(A[i], A[A[i]]) end while end for for i := 0 to n - 1 if A[i] != i then print A[i] end if end for

El primer bucle permuta la matriz de modo que si el elemento x está presente al menos una vez, entonces una de esas entradas estará en la posición A[x] .

Tenga en cuenta que es posible que no se vea O (n) a primera vista, pero sí, aunque tiene un ciclo anidado, aún se ejecuta en O(N) tiempo. Un intercambio solo ocurre si hay una i tal que A[i] != i , y cada intercambio establece al menos un elemento tal que A[i] == i , donde eso no era verdadero antes. Esto significa que el número total de intercambios (y, por tanto, el número total de ejecuciones del cuerpo del ciclo while) es como máximo N-1 .

El segundo ciclo imprime los valores de x para los cuales A[x] no es igual a x , ya que el primer ciclo garantiza que si x existe al menos una vez en el conjunto, uno de esos casos estará en A[x] , esto significa que imprime esos valores de x que no están presentes en la matriz.

(Enlace Ideone para que pueda jugar con él)


No es realmente bonito, pero al menos es fácil ver las propiedades O (N) y O (1). Básicamente escaneamos la matriz y, para cada número, vemos si la posición correspondiente ha sido marcada ya visto una vez (N) o ya visto varias veces (N + 1). Si está marcado ya visto una vez, lo imprimimos y lo marcamos ya visto varias veces. Si no está marcado, lo marcamos ya visto una vez y movemos el valor original del índice correspondiente a la posición actual (el marcado es una operación destructiva).

for (i=0; i<a.length; i++) { value = a[i]; if (value >= N) continue; if (a[value] == N) { a[value] = N+1; print value; } else if (a[value] < N) { if (value > i) a[i--] = a[value]; a[value] = N; } }

o, mejor aún (más rápido, a pesar del doble bucle):

for (i=0; i<a.length; i++) { value = a[i]; while (value < N) { if (a[value] == N) { a[value] = N+1; print value; value = N; } else if (a[value] < N) { newvalue = value > i ? a[value] : N; a[value] = N; value = newvalue; } } }


Para N relativamente pequeño, podemos usar operaciones de div / mod

n.times do |i| e = a[i]%n a[e] += n end n.times do |i| count = a[i]/n puts i if count > 1 end

No C / C ++ pero de todos modos

http://ideone.com/GRZPI


Si la matriz no es demasiado grande, esta solución es más simple. Crea otra matriz del mismo tamaño para marcar.

1 Crea un mapa de bits / matriz del mismo tamaño que tu matriz de entrada

int check_list[SIZE_OF_INPUT]; for(n elements in checklist) check_list[i]=0; //initialize to zero

2 escanee su matriz de entrada e incremente su recuento en la matriz anterior

for(i=0;i<n;i++) // every element in input array { check_list[a[i]]++; //increment its count }

3 Ahora escanee el conjunto check_list e imprima el duplicado ya sea una vez o tantas veces que se hayan duplicado

for(i=0;i<n;i++) { if(check_list[i]>1) // appeared as duplicate { printf(" ",i); } }

Por supuesto, se necesita el doble de espacio consumido por la solución dada anteriormente, pero la eficiencia del tiempo es O (2n) que es básicamente O (n).


Supongamos que presentamos este conjunto como una estructura de datos de gráfico unidireccional: cada número es un vértice y su índice en el conjunto apunta a otro vértice que forma un borde del gráfico.

Para una mayor simplicidad, tenemos los índices 0 a n-1 y el rango de número desde 0..n-1. p.ej

0 1 2 3 4 a[3, 2, 4, 3, 1]

0 (3) -> 3 (3) es un ciclo.

Respuesta: simplemente recorra la matriz dependiendo de los índices. si a [x] = a [y] entonces es un ciclo y por lo tanto se duplica. Salte al siguiente índice y continúe de nuevo y así sucesivamente hasta el final de una matriz. Complejidad: O (n) tiempo y O (1) espacio.


Un pequeño código python para demostrar el método de caf anterior:

a = [3, 1, 1, 0, 4, 4, 6] n = len(a) for i in range(0,n): if a[ a[i] ] != a[i]: a[a[i]], a[i] = a[i], a[a[i]] for i in range(0,n): if a[i] != i: print( a[i] )


Una solución en C es:

#include <stdio.h> int finddup(int *arr,int len) { int i; printf("Duplicate Elements ::"); for(i = 0; i < len; i++) { if(arr[abs(arr[i])] > 0) arr[abs(arr[i])] = -arr[abs(arr[i])]; else if(arr[abs(arr[i])] == 0) { arr[abs(arr[i])] = - len ; } else printf("%d ", abs(arr[i])); } } int main() { int arr1[]={0,1,1,2,2,0,2,0,0,5}; finddup(arr1,sizeof(arr1)/sizeof(arr1[0])); return 0; }

Es O (n) el tiempo y O (1) la complejidad del espacio.


La brillante respuesta de caf imprime cada número que aparece k veces en la matriz k-1 veces. Ese es un comportamiento útil, pero la pregunta posiblemente requiera que cada duplicado se imprima una sola vez, y alude a la posibilidad de hacer esto sin soplar los límites de tiempo lineal / espacio constante. Esto se puede hacer reemplazando su segundo ciclo con el siguiente pseudocódigo:

for (i = 0; i < N; ++i) { if (A[i] != i && A[A[i]] == A[i]) { print A[i]; A[A[i]] = i; } }

Esto explota la propiedad de que después de que se ejecuta el primer bucle, si cualquier valor m aparece más de una vez, entonces se garantiza que una de esas apariencias está en la posición correcta, es decir, A[m] . Si tenemos cuidado, podemos usar esa ubicación "doméstica" para almacenar información sobre si se han impreso o no duplicados.

En la versión de caf, mientras revisábamos el conjunto, A[i] != i Implicaba que A[i] es un duplicado. En mi versión, confío en una invariante ligeramente diferente: que A[i] != i && A[A[i]] == A[i] implica que A[i] es un duplicado que no hemos visto antes . (Si deja caer la parte "que no hemos visto antes", puede verse que el resto está implícito en la verdad de la invariante de caf, y la garantía de que todos los duplicados tienen alguna copia en una ubicación de origen). Esta propiedad se mantiene en al principio (después de que termine el 1er bucle de caf) y muestro debajo que se mantiene después de cada paso.

A medida que avanzamos en la matriz, el éxito en la parte A[i] != i de la prueba implica que A[i] podría ser un duplicado que no se había visto antes. Si no lo hemos visto antes, entonces esperamos que la ubicación de origen de A[i] apunte a sí misma, eso es lo que se verifica en la segunda mitad de la condición if . Si ese es el caso, lo imprimimos y modificamos la ubicación de origen para señalar el primer duplicado encontrado, creando un "ciclo" de 2 pasos.

Para ver que esta operación no altera nuestro invariante, suponga que m = A[i] para una posición particular que satisface A[i] != i && A[A[i]] == A[i] . Es obvio que el cambio que hacemos ( A[A[i]] = i ) funcionará para evitar que otras apariciones de m no sean del hogar se emitan como duplicados al causar la falla de la segunda mitad de sus condiciones, pero ¿funcionará? cuando llego a la ubicación de casa, m ? Sí, lo hará, porque ahora, aunque en este nuevo i encontramos que la primera mitad de la condición if , A[i] != i , es verdadera, la segunda mitad prueba si la ubicación a la que apunta es una ubicación de inicio y encuentra que no lo es. En esta situación, ya no sabemos si m o A[m] fue el valor duplicado, pero sabemos que de cualquier manera, ya se ha informado , porque se garantiza que estos 2 ciclos no aparecerán en el resultado del primer ciclo de caf. (Tenga en cuenta que si m != A[m] entonces exactamente uno de m A[m] ocurre más de una vez, y el otro no ocurre en absoluto).


static void findrepeat() { int[] arr = new int[7] {0,2,1,0,0,4,4}; for (int i = 0; i < arr.Length; i++) { if (i != arr[i]) { if (arr[i] == arr[arr[i]]) { Console.WriteLine(arr[i] + "!!!"); } int t = arr[i]; arr[i] = arr[arr[i]]; arr[t] = t; } } for (int j = 0; j < arr.Length; j++) { Console.Write(arr[j] + " "); } Console.WriteLine(); for (int j = 0; j < arr.Length; j++) { if (j == arr[j]) { arr[j] = 1; } else { arr[arr[j]]++; arr[j] = 0; } } for (int j = 0; j < arr.Length; j++) { Console.Write(arr[j] + " "); } Console.WriteLine(); }