la caf est génial réponse imprime chaque numéro qui apparaît à k fois dans le tableau k-1 fois. C'est utile de comportement, mais la question sans doute des appels pour chaque duplicata imprimé une seule fois, et il fait allusion à la possibilité de faire cela sans dépasser le temps linéaire/de la constante de l'espace de limites. Cela peut être fait en remplacement de son deuxième boucle avec le pseudo-code suivant:
for (i = 0; i < N; ++i) {
if (A[i] != i && A[A[i]] == A[i]) {
print A[i];
A[A[i]] = i;
}
}
Cela permet d'exploiter la propriété qu'après la première boucle s'exécute, si aucune valeur m
apparaît plus d'une fois, une de ces apparitions est garanti d'être dans la bonne position, à savoir l' A[m]
. Si nous sommes prudents, nous pouvons utiliser cette "maison" emplacement de stockage des informations quant à savoir si tous les doublons ont été imprimés ou non.
En fac de version, que nous sommes allés à travers le tableau, A[i] != i
implicite qu' A[i]
est un doublon. Dans ma version, je compte sur un peu différente, invariant: c' A[i] != i && A[A[i]] == A[i]
implique qu' A[i]
est un doublon que nous n'avons pas vu avant. (Si vous laissez tomber le "que nous n'avons pas vu avant," la partie, le reste peut être vu pour être implicites par la vérité de la caf de l'invariant, et la garantie que tous les doublons ont quelques copier dans la position d'origine.) Cette propriété détient au départ (après la caf de la 1ère boucle se termine) et je montre ci-dessous que c'est maintenu après chaque étape.
Comme nous passons par le tableau, le succès sur l' A[i] != i
partie de l'épreuve implique qu' A[i]
pourrait être un doublon qui n'a pas été vu avant. Si nous n'avons pas vu avant, puis nous nous attendons A[i]
s'domicile à point à elle-même, c'est ce qui est testé par la deuxième moitié de l' if
condition. Si c'est le cas, nous l'imprimer et de modifier l'emplacement du domicile au point de retour pour ce premier trouvé en double, la création d'un 2-step "cycle".
De voir que cette opération ne modifie pas notre invariant, supposons m = A[i]
pour un poste particulier, i
satisfaction A[i] != i && A[A[i]] == A[i]
. Il est évident que le changement que nous faisons (A[A[i]] = i
) sera à éviter à d'autres de les occurrences de m
de sortie comme des doublons en causant de la 2e moitié de leur if
conditions d'échouer, mais ça va fonctionner quand i
arrive à l'emplacement du domicile, m
? Oui, parce que maintenant, même si à ce nouveau i
nous constatons que le 1er semestre de l' if
condition, A[i] != i
, est vrai, de la 2e moitié teste si l'endroit est un lieu d'accueil et constate qu'il ne l'est pas. Dans cette situation, on ne sait plus si m
ou A[m]
a été le double de la valeur, mais nous savons que de toute façon, il a déjà été signalé, car ces 2 cycles sont garantis de ne pas apparaître dans le résultat de la caf de la 1ère boucle. (Notez que si m != A[m]
alors exactement l'une des m
et A[m]
plus d'une fois, et les autres ne se produit pas à tous.)