A resposta brilhante do caf imprime cada número que aparece k vezes na matriz k-1 vezes. Esse é um comportamento útil, mas é indiscutível que a questão exige que cada duplicado seja impresso apenas uma vez, e ele alude à possibilidade de fazer isso sem soprar os limites lineares de tempo / espaço constante. Isso pode ser feito substituindo seu segundo loop pelo seguinte pseudocódigo:
for (i = 0; i < N; ++i) {
if (A[i] != i && A[A[i]] == A[i]) {
print A[i];
A[A[i]] = i;
}
}
Isso explora a propriedade que após a execução do primeiro loop, se algum valor maparecer mais de uma vez, é garantido que uma dessas aparências esteja na posição correta, a saber A[m]. Se tomarmos cuidado, podemos usar esse local "residencial" para armazenar informações sobre se alguma duplicata foi impressa ou não.
Na versão caf, conforme examinamos a matriz, A[i] != iisso implicava A[i]uma duplicata. Na minha versão, confio em uma invariante ligeiramente diferente: isso A[i] != i && A[A[i]] == A[i]implica que A[i]é uma duplicata que não vimos antes . (Se você soltar a parte "que não vimos antes"), o resto poderá ser implícito na verdade invariável do caf e na garantia de que todas as duplicatas têm uma cópia em um local residencial. o início (após o 1º loop do caf terminar) e mostro abaixo que ele é mantido após cada etapa.
À medida que avançamos na matriz, o sucesso por A[i] != iparte do teste implica que A[i] pode ser uma duplicata que não foi vista antes. Se não vimos isso antes, esperamos que A[i]a localização da casa aponte para si mesma - é isso que é testado na segunda metade da ifcondição. Se for esse o caso, imprimimos e alteramos o local da residência para apontar para essa primeira duplicata encontrada, criando um "ciclo" em duas etapas.
Para ver que essa operação não altera nossa invariante, suponha m = A[i]que uma determinada posição seja isatisfatória A[i] != i && A[A[i]] == A[i]. É óbvio que a alteração que fazemos ( A[A[i]] = i) funcionará para impedir que outras ocorrências não domésticas msejam reproduzidas como duplicatas, causando a iffalha da segunda metade de suas condições, mas funcionará quando ichegar ao local de origem m? Sim, sim, porque agora, embora neste novo iachemos que a 1ª metade da ifcondição A[i] != ié verdadeira, a 2ª metade testa se o local para o qual aponta é um local de origem e acha que não é. Nessa situação, não sabemos mais se foi mou A[m]não o valor duplicado, mas sabemos que, de qualquer maneira,já foi relatado , porque esses 2 ciclos garantem que não apareçam no resultado do 1º loop do caf. (Observe que se m != A[m]exatamente um de me A[m]ocorre mais de uma vez e o outro não ocorre).
a[a[i]], e a restrição de espaço O (1) indica que aswap()operação é a chave.