Existem estruturas de dados eficientes para representar partições definidas. Essas estruturas de dados têm boas complexidades de tempo para operações como Union e Find, mas não são particularmente eficientes em termos de espaço.
O que é uma maneira eficiente de espaço para representar uma partição de um conjunto?
Aqui está um possível ponto de partida:
Eu sei que o número de partições de um conjunto com elementos é , o número sino . Portanto, a complexidade ideal de espaço para representar uma partição de um conjunto com elementos é de bits. Para encontrar essa representação, poderíamos procurar um mapeamento individual entre (o conjunto de partições de um conjunto de elementos) e (o conjunto de números inteiros de a ).B N N N log 2 ( B N ) N 1 B N
Existe um mapeamento eficiente para calcular? O que quero dizer com "eficiente" é que desejo converter essa representação compacta para / de uma representação fácil de manipular (como uma lista de listas) no polinômio de tempo em ou .log 2 ( B N )
Respostas:
Você pode usar o modo como a fórmula de recorrência abaixo é derivada para localizar sua codificação: Isso é comprovado considerando-se quantos outros elementos existem na parte que contém o elemento . Se houver destes, então temos para eles e para particionar o restante.Bn+1=∑k=0n(nk)Bk. n+1 n−k ( nn - k) = ( nk) Bk
Usando isso, podemos fornecer um algoritmo recursivo para converter qualquer partição de em um número no intervalo . Suponho que você já tenha uma maneira de converter um subconjunto de tamanho de em um número no intervalo (um algoritmo desse tipo pode ser criado da mesma maneira usando a recorrência de Pascal ).n + 1 0 , ... , Bn + 1- 1 k { 1 , … , n } 0 , … , ( nk) -1 ( nk) = ( n-1k) + ( n-1k - 1)
Suponha que a parte que contém contenha outros elementos. Encontre o código . Calcule uma partição de "compactando" todos os elementos restantes para esse intervalo. recursivamente seu código . O novo código én + 1 k C1 1 { 1 , … , n - k } C2 C=∑l=0n−k−1(nl)Bl+C1Bn−k+C2.
Na outra direção, dado um código , encontre o único tal que e defina Desde , ele pode ser escrito como , onde . Agora codifica os elementos na parte que contém e codifica uma partição deC k ∑l=0n−k−1(nl)Bl≤C<∑l=0n−k(nl)Bl, C′=C−∑l=0n−k−1(nl)Bl. 0≤C′<(nk)Bn−k C1Bn−k+C2 0≤C2<Bn−k C1 n+1 C2 {1,…,n−k} n+1, que pode ser decodificado recursivamente. Para concluir a decodificação, é necessário "descompactar" a última partição para que ela contenha todo o elemento que não aparece na parte que contém .n+1
Aqui está como usar a mesma técnica para codificar um subconjunto de de tamanho , recursivamente. Se , o código é , então suponha que . Se , deixe ser um código de , como um subconjunto do tamanho de ; o código de é . Se , deixe ser um código de , como um subconjunto de tamanho de ; o código deS {1,…,n} k k=0 0 k>0 n∈S C1 S∖{n} k−1 {1,…,n−1} S C1 n∉S C1 1 S k { 1 , … , n - 1 } S é .C1 1+ ( n - 1k - 1)
Para decodificar um código , existem dois casos. Se , decodifique um subconjunto de de tamanho cujo código é , e produza . Caso contrário, decodifique um subconjunto de de tamanho cujo código é e faça a saída .C C< ( n - 1k - 1) S′ {1,…,n−1} k−1 C S′∪{n} S′ {1,…,n−1} k C−(n−1k−1) S′
fonte