Existe um algoritmo linear de riffle shuffle no tempo linear? Este é o algoritmo que algumas mãos especialmente hábeis são capazes de executar: dividir uniformemente uma matriz de entrada de tamanho uniforme e depois intercalar os elementos das duas metades.
Mathworld tem uma breve página sobre riffle shuffle . Em particular, estou interessado na variedade de saída aleatória que transforma a matriz de entrada 1 2 3 4 5 6 em 1 4 2 5 3 6. Observe que em sua definição, o comprimento da entrada é .
É fácil fazer isso em tempo linear se tivermos uma segunda matriz de tamanho ou mais útil. Primeiro copie os últimos elementos para a matriz. Então, supondo que a indexação baseado em 0, copiar os primeiros elementos de índices de a . Em seguida, copie os elementos da segunda matriz de volta para a matriz de entrada, mapeando os índices paran [ 0 , 1 , 2 , . . . , N - 1 ] [ 1 , 3 , 5 , . . . , 2 n - 1 ]. (Podemos trabalhar um pouco menos que isso, porque o primeiro e o último elementos da entrada não se movem.)
Uma maneira de tentar fazer isso no local envolve a decomposição da permutação em ciclos disjuntos e, em seguida, reorganizar os elementos de acordo com cada ciclo. Novamente, assumindo a indexação baseada em 0, a permutação envolvida no caso de 6 elementos é
Como esperado, o primeiro e o último elementos são pontos fixos e, se permutarmos os 4 elementos do meio, obtemos o resultado esperado.
Infelizmente, meu entendimento da matemática das permutações (e seus ) é baseado principalmente na wikipedia, e não sei se isso pode ser feito em tempo linear. Talvez as permutações envolvidas nesse embaralhamento possam ser rapidamente decompostas? Além disso, nem precisamos da decomposição completa. Apenas determinar um único elemento de cada um dos ciclos separados seria suficiente, pois podemos reconstruir o ciclo a partir de um de seus elementos. Talvez seja necessária uma abordagem completamente diferente.
Bons recursos na matemática relacionada são tão valiosos quanto um algoritmo. Obrigado!
Respostas:
O problema é surpreendentemente não trivial. Aqui está uma ótima solução de Ellis e Markov, fusão in situ e estável por meio do Perfect Shuffle (seção 7). Ellis, Krahn e Fan, computando os ciclos na permutação aleatória perfeita, conseguem selecionar "líderes de ciclo", à custa de mais memória. Também está relacionado o belo artigo de Fich, Munro e Poblete, Permuting In Place , que fornece um algoritmo geral de tempo para o modelo oracle. Se apenas um oráculo para a permutação estiver disponível, o algoritmo requer espaço logarítmico; se também temos um oráculo para o inverso, isso requer espaço constante.O(nlogn)
Agora, a solução de Ellis e Markov. Primeiro, suponha que . Em seguida o cálculo do baralhamento perfeito de ordem n reduz a computar a aleatória perfeito de ordens x e y , com uma rotação que precede as mesmas. Aqui está uma prova por exemplo ( n = 5 , x = 3 , y = 2 ): 012 345 67 89 012 567 34 89 051627 3849n=x+y n x y n=5 x=3 y=2
Ellis e Markov encontraram uma maneira fácil de calcular o shuffle perfeito quando , usando espaço constante e tempo linear. Usando isso, obtemos um algoritmo para calcular o shuffle perfeito para n arbitrário . Primeiro, escreva n = 2 k 0 + ⋯ + 2 k w usando a codificação binária de n e deixe n i = 2 k i + ⋯ + 2 k w . Gire o meio n 0 bits, embaralhe o lado direito 2 kn=2k n n=2k0+⋯+2kw n ni=2ki+⋯+2kw n0 bits. Ignorando os2 k 0 bitsà direita, gire osn1bitsdo meioe embaralhe os2 k 1 bitsà direita. E assim por diante. Observe que a rotação é fácil, pois os primeiros elementos rotacionados funcionam como líderes de ciclo. A complexidade total da rotação éO(n0+⋯+nw)=O(n), uma vez quen t + 1 <nt/2. A complexidade total dos shuffles internos éO(2k0 2k0 n1 2k1 O(n0+⋯+nw)=O(n) nt+1<nt/2 .O(2k0+⋯+2kw)=O(n)
Resta mostrar como calcular o shuffle perfeito quando . Na verdade, vamos ser capazes de identificar líderes de ciclo, seguindo trabalho clássico sobre colares (Fredricksen e Maiorana, colares de contas em k cores e k -ary de seqüências de Bruijn ; Fredricksen e Kessler, Um algoritmo para gerar colares de contas em duas cores )n=2k k k
Qual é a conexão? Afirmo que a permutação aleatória corresponde à mudança correta da representação binária. Aqui está uma prova por exemplo, para : 000 001 010 011 100 101 110 111 000 100 001 101 010 110 011 111 Portanto, para encontrar líderes de ciclo, precisamos encontrar um representante de cada classe de equivalência da rotação de cadeias binárias de comprimento k . Os documentos mencionados acima fornecem o seguinte algoritmo para gerar todos os líderes de ciclo. Comece com 0 kn=8
Por exemplo, quando isso gera a sequência 0000 , 0001 , 0010 , 0011 , 0101 , 0110 , 0111 , 1111 .n=16
Os líderes do ciclo são destacados.
fonte
Esta foi uma pergunta de propagação em cs.stackexchange.com e uma resposta está aqui: /cs/332/in-place-algorithm-for-interleaving-an-array/400#400
É uma explicação do artigo: http://arxiv.org/abs/0805.1598 .
fonte
O que acontece se você escrever o shuffle de rifles como uma função? E sem é o comprimento da matriz total, deixe n = m - 2 seja o comprimento da matriz após remover o primeiro e o último elemento. Em seguida, o índice embaralhado do índiceEu é f( i ) = 2 ⋅ i E se i ≤ n / 2 e f( i ) = 2 ⋅ ( imodn/2)−1 if i>n/2 . Then you can just "pointer jump" through the array, swapping by re-applying the function.
Assuming random access, this would be linear time while requiringO(1) extra words (for storing the value of the array at any given index), and so O(logn) extra space.
fonte