Inspirada nesta pergunta em que o solicitante deseja saber se o tempo de execução muda quando o comparador usado em um algoritmo de pesquisa padrão é substituído por um lançamento justo, e também pela falha proeminente da Microsoft em escrever um gerador de permutação uniforme, minha pergunta é assim :
Existe um algoritmo de classificação baseado em comparação que, dependendo da nossa implementação do comparador:
- retorne os elementos em ordem classificada ao usar um comparador verdadeiro (ou seja, a comparação faz o que esperamos em um algoritmo de classificação padrão)
- retorna uma permutação uniformemente aleatória dos elementos quando o comparador é substituído por uma troca de moeda justa (ou seja, retorna
x < y = true
com probabilidade 1/2, independentemente do valor de xey)
O código para o algoritmo de classificação deve ser o mesmo. É apenas o código dentro da "caixa preta" de comparação que pode mudar.
Respostas:
O seguinte algoritmo determinístico (sem o comparador) funciona para uma tupla de entrada :( a1 1, … , Umn)
Dada uma relação de ordem determinística como comparador, esse algoritmo classifica uma matriz no tempo pois o embaralhamento de Fisher-Yates é executado em O ( n ) usando "bits aleatórios" não aleatórios máximos de O ( log n ) (por exemplo, chamadas para o seu comparador ) em cada etapa e classificação de mesclagem tem a mesma complexidade assintótica. O resultado de (1) é totalmente inútil neste caso, mas, como é seguido por uma espécie real, isso não faz mal.O (nlogn ) O (n) O (logn )
Dado um giro real da moeda, pois o comparador (1) permite a matriz com igual probabilidade para cada permutação e se você realmente tiver que fazer (3) (você deixou de fora (2) ou (2) falhou em determinar a aleatoriedade)), isso não é verdade. dano porque a distribuição de seu resultado depende apenas da ordem de sua entrada, que é distribuída uniformemente entre todas as permutações por causa de (1); portanto, o resultado de todo o algoritmo também é uniformemente distribuído. O número de vezes que cada amostragem de aceitação-rejeição deve ser repetida é distribuído geometricamente (rejeitar com probabilidade ) e, portanto, tem um valor esperado<2. Cada repetição usa no máximobits delogn, portanto, a análise de tempo de execução é quase a mesma do caso determinístico, mas obtemos apenas umtempodeexecução esperadodeO(nlogn), com a possibilidade de não terminação (termina comquase certeza).< 12 < 2 registron O (nlogn )
Como Joe apontou: Se você não gostar do teste do primeiro bit em (1), faça (3) e depois (1) e use que sempre é 0 , pois a matriz já está classificada no caso determinístico. Além disso, você deve subtrair seu número aleatório do limite superior do intervalo no loop, porque o limite superior do número aleatório gera a permutação idêntica. Mas lembre-se de que (2) é proibido, pois você sempre deve fazer o embaralhamento no caso de resgate.uman< a1 1 0 0
Você pode até usar as mesmas chamadas para o seu comparador para (1) e (3), mas provar que o resultado é distribuído uniformemente é pelo menos muito mais difícil, se possível.
O algoritmo a seguir não possui fases distintas para ordenar e ordenar, mas é assintoticamente mais lento. É essencialmente tipo de inserção com pesquisa binária . Vou usar para indicar a entrada e b k = ( b k , 1 , ... , b k , k ) para indicar o resultado após o k -ésimo rodada:
Observe que esse algoritmo é ineficiente em ambos os modos, comparado à ordenação aleatória e mesclada de Fisher-Yates, pois inserir um elemento em uma posição arbitrária é caro se o uso de uma matriz e a pesquisa binária precisar de tempo linear ao usar uma lista. Mas talvez uma modificação da classificação da pilha ou da árvore de maneira semelhante possa levar a um algoritmo mais rápido.
fonte
fonte