¿Quieres eliminar algunos elementos de una lista que se existía en otra lista

Karan:

Tengo una lista de suponer

listA=[679,890,907,780,5230,781]

y desea eliminar algunos elementos que existían en otra

listB=[907,5230]

en la complejidad del tiempo mínimo?

Puedo hacer este problema mediante el uso de dos "para los bucles" significa O (n2) Tiempo de complejidad, pero quiero reducir esta complejidad de O (n log (n)) u O (n)? ¿Es posible?

AVI:

Es posible - si una de las listas está ordenada. Suponiendo que la lista A se clasifica y la lista B es sin clasificar, con dimensiones respectivas My N, la complejidad de tiempo mínimo para eliminar todos los elementos de la lista de B de la lista A habrá O((N+M)*log(M)). La forma en que se puede lograr esto es mediante la búsqueda binaria - cada búsqueda de un elemento en la lista A toma O(log(M))tiempo, y hay Noperaciones de búsqueda (uno para cada elemento en la lista B). Debido a que toma O(M*log(M))tiempo para ordenar a A, que es más eficiente para grandes listas para ordenar y retire todos los elementos, con tiempo total complejidad O((N+M)*log(M)).

Por otro lado, si usted no tiene una lista ordenada, sólo tiene que utilizar Collection.removeAll , que tiene un tiempo de complejidad O(M*N)en este caso. La razón de este tiempo la complejidad es que removeAllhace (por defecto) como el siguiente pseudocódigo:

public boolean removeAll(Collection<?> other)
    for each elem in this list
        if other contains elem
            remove elem from this list

Dado que containstiene un tiempo de complejidad O(N)para las listas, y que terminan haciendo Miteraciones, esto lleva su O(M*N)tiempo en total.

Por último, si desea reducir al mínimo el tiempo de complejidad removeAll(con un rendimiento real posiblemente degradado) puede hacer lo siguiente:

List<Integer> a = ...
List<Integer> b = ...
HashSet<Integer> lookup = new HashSet<>(b);
a.removeAll(lookup);

Para valores negativos de b, el tiempo de construcción lookuppodría tardar hasta el tiempo O(N*log(N)), como se muestra aquí (ver "llaves patológicamente distribuidos"). Después de eso, la invocación removeAllse llevará O(1)a containsmás de Miteraciones, teniendo O(M)tiempo para ejecutarse. Por lo tanto, la complejidad del tiempo de este enfoque es O(M + N*log(N)).

Por lo tanto, hay tres enfoques aquí. Uno te ofrece la complejidad del tiempo O((N+M)*log(M)), otro te ofrece la complejidad del tiempo O(M*N), y el último te ofrece la complejidad del tiempo O(M + N*log(N)). Teniendo en cuenta que los primeros y últimos enfoques son similares en complejidad del tiempo (como logtiende a ser muy pequeña incluso para un gran número), sugeriría ir con la ingenua O(M*N)para entradas pequeñas, y el más sencillo O(M + N*log(N))para las entradas de tamaño mediano. En el punto donde el uso de la memoria comienza a sufrir de la creación de un HashSet para almacenar los elementos de B (muy grandes entradas), yo por último cambiar a la más compleja O((N+M)*log(M))enfoque.

Usted puede encontrar una aplicación AbstractCollection.removeAll aquí .

Editar:
El primer enfoque no funciona tan bien para ArrayLists - eliminación de la mitad de la lista A lleva O(M)tiempo, al parecer. En su lugar, ordenar la lista B ( O(N*log(N))) y repite el proceso de la lista A, la eliminación de elementos, según proceda. Esto toma O((M+N)*log(N))tiempo y es mejor que el O(M*N*log(M))que se termina con al usar un ArrayList. Por desgracia, la "eliminación de elementos, según proceda" parte de este algoritmo requiere la creación de datos para almacenar los elementos no elimina da lugar O(M), como usted no tiene acceso a la matriz de datos interna de la lista A. En este caso, es estrictamente mejor ir con el enfoque HashSet. Esto se debe a (1) la complejidad del tiempo O((M+N)*log(N))es en realidad peor que la complejidad del tiempo para el método HashSet, y (2) el nuevo algoritmo no guarda en la memoria. Por lo tanto,utilice únicamente el primer enfoque cuando se tiene una lista con O(1)el tiempo para el retiro (por ejemplo LinkedList) y una gran cantidad de datos . De lo contrario, utilizar removeAll . Es más sencillo, a menudo más rápido, y apoyado por diseñadores de la biblioteca (por ejemplo ArrayList tiene un encargo de removeAll aplicación que le permite tomar lineal en lugar de tiempo cuadrática utilizando memoria adicional despreciable).

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=315033&siteId=1
Recomendado
Clasificación