2010-05-17 12 views
20

Tengo un número variable de ArrayList que necesito para encontrar la intersección de. Un límite realista en el número de conjuntos de cadenas probablemente sea alrededor de 35, pero podría ser más. No quiero ningún código, solo ideas sobre lo que podría ser eficiente. Tengo una implementación que estoy a punto de comenzar a codificar pero quiero escuchar algunas otras ideas.Encontrar de manera eficiente la intersección de un número variable de conjuntos de cadenas

Actualmente, con solo pensar en mi solución, parece que debería tener un tiempo de ejecución asintótico de Θ (n).

¡Gracias por cualquier ayuda!

tshred

Editar: Para aclarar, que en realidad sólo quiero saber es que hay una manera más rápida de hacerlo. Más rápido que Θ (n).

+0

¡Gracias por la ayuda a todos! Las cadenas están realmente dentro de los objetos en una lista de arreglos ya existente, esta es la razón por la que los dejaba en las matrices. Nunca he tenido que usar las clases de colecciones de Java que se mencionan, pero definitivamente las usaré. Aprecio las recomendaciones. Problema resuelto. – tshred

Respuesta

32

Set.retainAll() es cómo se encuentra la intersección de dos conjuntos. Si usa HashSet, entonces convertir su ArrayList a Set sy usar retainAll() en un bucle sobre todos ellos es en realidad O (n).

+1

Dale un golpe :) –

+1

Solo debes envolver una de las listas en un conjunto. – Hans

+0

Solo se espera que esté en O (n). ¡No es el peor caso! –

0

Ordene (n lg n) y luego realice búsquedas binarias (lg n).

2

La mejor opción sería usar HashSet para almacenar el contenido de estas listas en lugar de ArrayList. Si puede hacerlo, puede crear un HashSet temporal al que agregue los elementos que se intersectarán (use el método putAll (..)). Do tempSet.retainAll (storedSet) y tempSet contendrán la intersección.

4

Una idea más: si sus matrices/conjuntos son de diferentes tamaños, tiene sentido comenzar con los más pequeños.

1

Puede usar un solo HashSet. Su método add() devuelve falso cuando el objeto ya está en el conjunto. agregar objetos de las listas y marcar conteos de valores de retorno falsos le dará unión en el set + datos para el histograma (y los objetos que tienen un recuento + 1 igual al recuento de la lista son su intersección). Si arrojas los conteos a TreeSet, puedes detectar la intersección vacía temprano.

7

La respuesta aceptada está bien; como una actualización: desde Java 8 hay una forma un poco más eficiente de encontrar la intersección de dos Set s.

Set<String> intersection = set1.stream() 
    .filter(set2::contains) 
    .collect(Collectors.toSet()); 

La razón es ligeramente más eficiente es debido a que el enfoque original tuvo que añadir elementos de set1 que luego tuvo que retirar de nuevo si no estaban en set2. Este enfoque solo agrega al conjunto de resultados lo que necesita estar allí.

Estrictamente hablando, usted podría hacer esto también antes de Java 8, pero sin Stream s el código hubiera sido bastante más laborioso.

Si ambos conjuntos difieren considerablemente en tamaño, preferiría la transmisión por sobre la más pequeña.

+0

Buena nota de que no hay transmisión por encima de la más pequeña. Es porque el flujo continuo es iterado, mientras que el otro (más grande) conjunto es buscado (por hash para un 'HashSet', que es [O (1)] (https://stackoverflow.com/questions/6574916/hashset- complejidad de búsqueda)). –

Cuestiones relacionadas