Istnieją wydajne struktury danych do reprezentowania ustawionych partycji. Te struktury danych charakteryzują się dużą złożonością czasową dla operacji takich jak Union i Find, ale nie są szczególnie efektywne pod względem przestrzeni.
Jaki jest oszczędny przestrzennie sposób reprezentowania partycji zestawu?
Oto jeden z możliwych punktów wyjścia:
Wiem, że liczba partycji zestawu z elementami to , numer ty Bell . Zatem optymalna złożoność przestrzeni do reprezentowania partycji zestawu z elementami to bitów. Aby znaleźć taką reprezentację, moglibyśmy poszukać odwzorowania jeden na jednego między (zestawem partycji zestawu elementów) a (zestawem liczb całkowitych od do ). Nlog 2 ( B N ) N 1 B N
Czy istnieje takie mapowanie, które jest wydajne w obliczeniach? Rozumiem przez „wydajny” to, że chcę przekonwertować tę zwartą reprezentację na / z łatwej w obsłudze reprezentacji (takiej jak lista list) w wielomianie czasowym w lub .log 2 ( B N )
Odpowiedzi:
Aby znaleźć kodowanie, możesz użyć sposobu wyprowadzenia poniższej formuły rekurencyjnej:bn + 1= ∑k = 0n( nk) B.k.
Dowodzi tego rozważenie, ile innych elementów znajduje się w części zawierającej elementn + 1 . Jeśli jest ichn - k , to mamy( nn - k) = ( nk) wybory dla nich, ibk wybory dla podziału pozostałych.
Korzystając z tego, możemy podać algorytm rekurencyjny do konwersji dowolnej partycjin + 1 na liczbę z zakresu 0 , … , Bn + 1−1 . Zakładam, że masz już sposób konwertowania podzbiór rozmiarze k z {1,…,n} na liczbę w zakresie 0,…,(nk)−1 (taki algorytm można opracować w ten sam sposób, korzystając z powtarzalności Pascala( nk)=(n−1k)+(n−1k−1) ).
Załóżmy, że część zawierającan+1 zawiera k innych elementów. Znajdź ich kod C1 . Oblicz partycję {1,…,n−k} , „kompresując” wszystkie pozostałe elementy do tego zakresu. Rekurencyjnie oblicz kod C2 . Nowy kod to C=∑l=0n−k−1(nl)Bl+C1Bn−k+C2.
W przeciwnym kierunku, biorąc pod uwagę kodC , znajdź unikalne k takie, że
∑l=0n−k−1(nl)Bl≤C<∑l=0n−k(nl)Bl,
i określają
C′=C−∑l=0n−k−1(nl)Bl.
Ponieważ0≤C′<(nk)Bn−k , można zapisać jakoC1Bn−k+C2 , gdzie0≤C2<Bn−k . TerazC1 koduje elementy w części zawierającejn+1 , aC2 koduje partycję{1,…,n−k} , które można dekodować rekurencyjnie. Aby zakończyć dekodowanie, musisz „zdekompresować” drugą partycję, aby zawierała cały element nie pojawiający się w części zawierającej n+1 .
Oto jak zastosować tę samą technikę do rekurencyjnego kodowania podzbioruS wielkości {1,…,n} o rozmiarze k . Jeśli k=0 wówczas kod wynosi 0 , więc załóżmy, że k>0 . Jeśli n∈S niech C1 będzie kodem S∖{n} , jako podzbiorem wielkości k−1 z {1,…,n−1} ; kod S to C1 . Jeśli n∉S niech C1 będzie kod S , jako podzbiór o rozmiarze k o {1,…,n−1} ; kod S to C1+(n−1k−1) .
Aby zdekodować kodC , istnieją dwa przypadki. Jeśli C<(n−1k−1) a następnie zdekoduj podzbiórS′ o wartości{1,…,n−1} o rozmiarzek−1 którego kodem jestC , iwyślijS′∪{n} . W przeciwnym razie zdekoduj podzbiórS′ o wartości{1,…,n−1} o rozmiarzek którego kod toC−(n−1k−1) i wyjścieS′ .
źródło