Java merge 2 collections in O(1)
Muszę być w stanie połączyć 2 duże zbiory w 1. Jakiego typu kolekcji mogę użyć najlepiej? Nie potrzebuję przypadkowego dostępu do poszczególnych elementów. Zwykle wybrałbym linkedlist, jednak nie mogę połączyć 2 linkedlist w Javie z runtime O(1), co można zrobić w wielu innych językach, ponieważ będę musiał skopiować każdy element do nowej listy.
Edit: dziękuję za wszystkie odpowiedzi. Wasze odpowiedzi były bardzo pomocne i udało mi się wykonać zadanie. Następnym razem użyję moja własna implementacja linked list na początek.
8 answers
Możesz utworzyć skonkatenowany Iterable
widok W O(1) używając jednego z Iterabli Guava 'S .metody concat :
Iterable<T> combined = Iterables.concat(list1, list2);
Pozwoli to na iterację wszystkich elementów obu list jako jednego obiektu bez kopiowania żadnych elementów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-03 14:45:28
Najprostszym rozwiązaniem jest tutaj lista list. Oznacza to, że potrzebujesz prostych funkcji owijania, ale nic skomplikowanego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-03 14:01:57
W teorii, możesz połączyć 2 połączone listy W O(1), Ponieważ wszystko, co musisz zrobić, to skierować ostatni węzeł pierwszego do pierwszego węzła drugiego (zakładając, że masz te odniesienia).
Metoda zbioru addAll
wydaje się sugerować czas działania O(n), ponieważ mówią o iteratorach. Szczegóły mogą być specyficzne dla JVM...
Myślę, że nie ma żadnych zbiorów, które połączyłyby się w O (n). Może sam będziesz musiał to zrobić.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-03 14:05:08
Myślę, że najlepiej byłoby stworzyć implementację listy, która jako swoje argumenty przyjmuje List>, a następnie deleguje. Innymi słowy, mieć listę list i połączyć je, aby działać jako jedna lista. Kiedy przechodzisz obok elementów listy 1, zaczynasz patrzeć na listę 2.
Z jakiegoś powodu myślałem, że guava ma taką listę. Ale nie mogę znaleźć tego w ich Javadoc.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-03 14:07:59
Jeślipo prostu Chcesz mieć kolekcje obiektów i scalać je w czasie O(1) i nie masz nic przeciwko implementacji własnej struktury danych, najprostszym sposobem na to jest użycie niezrównoważonego drzewa binarnego: każdy węzeł jest albo liściem (przechowującym wartość), albo kombinacją dwóch drzew i możesz zaimplementować je jako dwie klasy z abstrakcyjną klasą nadrzędną lub interfejsem. Do ekstrakcji pierwiastków można użyć trawersu o pierwszej głębokości.
Jest to zasadniczo to samo, co ColinD sugestia konkatenacji iteratora, ale więcej gołych kości.
haczyk polega na tym, że iteracja nad tą kolekcją będzie , a nie być O(n)! Będzie O (n + m) Gdzie m jest liczbą wykonanych połączeń (ponieważ każdy z nich jest węzłem do przejścia). Jest to prawda zarówno mojego rozwiązania, jak i Colinda. Nie wiem, czy to prawda dla wszystkich możliwych rozwiązań tego problemu.
Mniejsza o powyższe. W ramach tego programu każdy merge dodaje co najmniej jeden element, więc m n i tak koszt iteracji jest nadal O (n). (Jeśli używasz konkatenacji iteratora, upewnij się, że często nie łączysz pustych iteratorów, ponieważ zwiększyłoby to koszt.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-04 01:29:56
Scalanie połączonych list jest rzeczywiście O(1) i można traktować listy oparte na tablicach w ten sam sposób, tzn. mając wiele obiektów połączonych między sobą.
Istnieją implementacje powyższego, jest to szybsze niż ArrayList podczas usuwania / wstawiania od środka / startu. I iteracja jest praktycznie taka sama. Losowy dostęp może być jednak nieco wolniejszy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-03 14:14:01
Chciałem zasugerować klasę CompositeCollection z apache.commons, ale patrząc na kod źródłowy to działa również w O (n). Jeśli potrzebujesz tylko iterować nad elementami i nie chcesz korzystać z kolekcji Google zgodnie z sugestią Colinda, możesz łatwo utworzyć własny iterator kompozytowy, np.
public class CompositeCollectionIterator<T> implements Iterator<T>{
private Iterator<T>[] iterators;
private int currentIteratorIndex = 0;
public CompositeCollectionIterator( Collection<T>... aCollections ) {
iterators = new Iterator[ aCollections.length];
for ( int i = 0, aCollectionsLength = aCollections.length; i < aCollectionsLength; i++ ) {
Collection<T> collection = aCollections[ i ];
iterators[i] = collection.iterator();
}
}
public boolean hasNext() {
if ( iterators[currentIteratorIndex].hasNext() ) return true;
else if ( currentIteratorIndex < iterators.length - 1 ){
currentIteratorIndex++;
return hasNext();
}
return false;
}
public T next() {
return iterators[currentIteratorIndex].next();
}
public void remove() {
iterators[currentIteratorIndex].remove();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-03 14:36:07
Używając dwóch połączonych list jako kolekcji i przechowując wskaźniki do pierwszego i ostatniego elementu każdej listy(oba wskaźniki potencjalnie wymagają aktualizacji podczas dodawania/usuwania elementów), możesz połączyć obie listy W O (1) - po prostu podłącz ostatni element pierwszej listy do pierwszego elementu drugiej listy i odpowiednio dostosuj pierwszy/ostatni wskaźnik.
Obawiam się, że będziesz musiał zwijać własną implementację linkowanych list w Javie, ponieważ nie masz bezpośredni dostęp do bazowych węzłów LinkedList
, dlatego nie można połączyć ostatniego elementu pierwszej listy z pierwszym elementem drugiej listy.
Na szczęście łatwo jest znaleźć implementacje linked list w Javie, ponieważ jest to bardzo popularny temat w kursach struktury danych. Na przykład tutaj jest jeden - wiem, nazwy są w języku hiszpańskim, ale kod w ListaEncadenada
("LinkedList") i NodoLista
("ListNode") jest dość prosty i powinien być oczywisty, a co najważniejsze - implementacja zawiera wskaźniki do pierwszego i ostatniego elementu listy i może być łatwo modyfikowana do własnych potrzeb.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-04 01:45:55