Dane są dwa zbiory liczb. Napisz algorytm, który sprawdzi czy podane zbiory są rozłączne. Postaraj się znaleźć optymalne rozwiązanie, które będzie szybko zwracać odpowiedź. W tym artykule zostaną przedstawione dwa sposoby na rozwiązanie tego problemu.
Dany jest zbiór A = {1, 2, 3} oraz B = {4, 5, 6}. Zbiory te nie mają ze sobą ani jednego wspólnego elementu, a więc są rozłączne. Jednak zarówno A jak i zbiór B z zbiorem B = {3} mają dokładnie jeden wspólny element, a więc są nierozłączne.
Najmniej optymalnym, ale skutecznym sposobem jest rozwiązanie siłowe. Polega ono na porównaniu każdego elementu zbioru A z każdym elementem zbioru B. W praktyce oznacza to, że jeśli zbiór A ma n elementów, a zbiór B m to złożoność wynosi O(nm) co dla zbiorów o tej samej ilości elementów daje złożoność kwadratową. Oto przykładowa implementacja:
Kod składa się z dwóch zagnieżdżonych pętli w których wykonywane jest porównanie aktualnie wybranych elementów. W przypadku, gdy oba wybrane elementy z różnych zbiorów są sobie równe to algorytm zwraca fałsz. Oznacza to, że zbiory nie są rozłączne.
Słabym punktem algorytmu przedstawionego powyżej jest wyszukiwanie elementu z jednego zbioru w drugim przy wkorzystaniu wyszukiwania liniowego. Niestety ze względu na to, że elementy zbioru nie są podane w kolejności rosnącej / malejącej to nie może zostać wykorzystane wyszukiwanie binarne. Dane jednak zawsze można wpierw posortować w jednej tablicy i dopiero wykonywać wyszukiwanie. Jednak czy jest to najbardziej optymalne rozwiązanie? Jak wiadomo sortowanie też potrzebuje trochę czasu...
Jeden z pomysłów, który nie wymaga sortowania i jest w stanie porównać zbiory w rozsądnym czasie, jest wykorzystanie hashowania. Oczywiście skuteczność takiego rozwiązania będzie zależeć od tego jak dobrze funkcja hashująca porozdziela dane.
Algorytm ponownie składa się z dwóch pętli, ale tym razem w pierwszej jest tworzona mapa hashy na podstawie zbioru 1, a następnie elementy zbioru 2 są wyszukiwane w mapie. Jeśli żaden klucz nie zawiera kolejnej liczby z zbioru 2 to należy zwrócić prawdę czyli, że zbiory są rozłączne. Oto przykładowa funkcja hashująca dane:
Powyższa funkcja zakłada, że liczby są rozmieszczone równomiernie między maskimum, a minimum.
Poniższy fragment kodu wczytuje dwa zbiory liczb, a następnie wypisuje komunikat czy są one rozłączne.