Jaki jest kompaktowy sposób reprezentowania partycji zestawu?

11

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 N 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 ). NBNNlog 2 ( B N ) N 1 B NNlog2(BN)N1BN

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 )Nlog2(BN)

Cberzan
źródło
zastanawiasz się, jak daleko może być od naiwnego / naturalnego kodowania polegającego na przypisaniu unikalnych liczb całkowitych do każdego elementu zestawu, w którym liczba całkowita reprezentuje partycję #? może to „niezbyt duża różnica” ...log2(BN)
wer 16'13

Odpowiedzi:

7

Aby znaleźć kodowanie, możesz użyć sposobu wyprowadzenia poniższej formuły rekurencyjnej:

bn+1=k=0n(nk)bk.
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, ibkwybory dla podziału pozostałych.

Korzystając z tego, możemy podać algorytm rekurencyjny do konwersji dowolnej partycji n+1 na liczbę z zakresu 0,,Bn+11 . 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)=(n1k)+(n1k1) ).

Załóżmy, że część zawierająca n+1 zawiera k innych elementów. Znajdź ich kod C1 . Oblicz partycję {1,,nk} , „kompresując” wszystkie pozostałe elementy do tego zakresu. Rekurencyjnie oblicz kod C2 . Nowy kod to

C=l=0nk1(nl)Bl+C1Bnk+C2.

W przeciwnym kierunku, biorąc pod uwagę kod C , znajdź unikalne k takie, że

l=0nk1(nl)BlC<l=0nk(nl)Bl,
i określają
C=Cl=0nk1(nl)Bl.
Ponieważ0C<(nk)Bnk, można zapisać jakoC1Bnk+C2, gdzie0C2<Bnk. TerazC1koduje elementy w części zawierającejn+1, aC2koduje partycję{1,,nk}, 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 podzbioru S 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 nS niech C1 będzie kodem S{n} , jako podzbiorem wielkości k1 z {1,,n1}; kod S to C1 . Jeśli nS niech C1 będzie kod S , jako podzbiór o rozmiarze k o {1,,n1} ; kod S to C1+(n1k1) .

Aby zdekodować kod C , istnieją dwa przypadki. Jeśli C<(n1k1) a następnie zdekoduj podzbiórSo wartości{1,,n1}o rozmiarzek1którego kodem jestC, iwyślijS{n}. W przeciwnym razie zdekoduj podzbiórSo wartości{1,,n1}o rozmiarzekktórego kod toC(n1k1) i wyjścieS.

Yuval Filmus
źródło
Doskonała odpowiedź; Dziękuję Ci. Drobny błąd: w szkicu wzoru dla formuły rekurencyjnej u góry myślę, że masz na myśli „jest tych” zamiast „jest ich k ” - wtedy pozostałe k elementów można podzielić na B k sposoby nkkkBk
cberzan