2010-05-17 13 views
20

Ho un numero variabile di ArrayList di cui ho bisogno per trovare l'intersezione di. Un limite realistico al numero di serie di stringhe è probabilmente intorno ai 35 ma potrebbe essere più. Non voglio alcun codice, solo idee su ciò che potrebbe essere efficiente. Ho un'implementazione che sto per iniziare a programmare ma voglio ascoltare altre idee.Trovare in modo efficiente l'intersezione di un numero variabile di insiemi di stringhe

Attualmente, solo pensando alla mia soluzione, sembra che dovrei avere un runtime asintotico di Θ (n).

Grazie per qualsiasi aiuto!

tshred

Edit: Per chiarire, io in realtà voglio solo sapere c'è un modo più veloce per farlo. Più veloce di Θ (n).

+0

Grazie per l'aiuto a tutti! Le stringhe sono in realtà all'interno di oggetti in una lista di array già esistente, questo è il motivo per cui li stavo lasciando negli array. Non ho mai dovuto usare le classi di collezioni Java menzionate, ma le userò sicuramente. Apprezzo le raccomandazioni. Problema risolto. – tshred

risposta

32

Set.retainAll() è come si trova l'intersezione di due set. Se si utilizza HashSet, la conversione dei numeri da ArrayList a Set e l'uso di retainAll() in un ciclo su tutti loro è in realtà O (n).

+1

Picchiami :) –

+1

Devi solo inserire uno degli elenchi in un set. – Hans

+0

Si prevede che sia solo in O (n). Non è il caso peggiore! –

0

Ordinarli (n lg n) e quindi eseguire ricerche binarie (lg n).

2

L'opzione migliore sarebbe utilizzare HashSet per archiviare il contenuto di questi elenchi anziché ArrayList. Se puoi farlo, puoi creare un HashSet temporaneo a cui aggiungi gli elementi da intersecare (usa il metodo putAll (..)). Do tempSet.retainAll (storedSet) e tempSet conterrà l'intersezione.

4

Un'ultima idea: se i tuoi array/set sono di dimensioni diverse, ha senso iniziare con il più piccolo.

1

È possibile utilizzare un singolo Hashset. Il suo metodo add() restituisce false quando l'oggetto è già presente nel set. l'aggiunta di oggetti dalle liste e il conteggio dei conteggi di valori di ritorno falsi ti daranno l'unione nel set + i dati per l'istogramma (e gli oggetti che hanno un conteggio + 1 uguale al conteggio delle liste sono l'intersezione). Se si lanciano i conteggi a TreeSet, è possibile rilevare l'intersezione vuota in anticipo.

7

La risposta accettata va bene; come aggiornamento: da Java 8 c'è un modo leggermente più efficiente per trovare l'intersezione di due Set s.

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

Il motivo è leggermente più efficiente è perché l'approccio originale aveva per aggiungere elementi di set1 poi dovuto togliere di nuovo se non fossero in set2. Questo approccio aggiunge solo al risultato impostato ciò che deve essere presente.

Strettamente parlando si potrebbe fare questo pre Java 8 pure, ma senza Stream s il codice sarebbe stato un po 'più laborioso.

Se entrambi i set differiscono notevolmente in termini di dimensioni, si preferisce lo streaming su quello più piccolo.

+0

Buona nota senza streaming su quella più piccola. È perché il flusso viene iterato, mentre viene cercato l'altro (più grande) set (da hash per un 'HashSet', che è [O (1)] (https://stackoverflow.com/questions/6574916/hashset- look-up-complessità)). –

Problemi correlati