caf'in parlak cevabı , dizide k-1 kez görünen her sayıyı yazdırır. Bu yararlı bir davranış, ancak soru tartışmalı olarak her bir kopyasının yalnızca bir kez basılmasını gerektiriyor ve bunu doğrusal zaman / sabit uzay sınırlarını aşmadan yapma olasılığını ima ediyor. Bu, ikinci döngüsünü aşağıdaki sözde kodla değiştirerek yapılabilir:
for (i = 0; i < N; ++i) {
if (A[i] != i && A[A[i]] == A[i]) {
print A[i];
A[A[i]] = i;
}
}
Bu, ilk döngü çalıştıktan sonra herhangi bir değer m
birden fazla görünürse, bu görünümlerden birinin doğru konumda olması garantilenmesi özelliğinden yararlanır, yaniA[m]
. Dikkatli olursak, herhangi bir kopyasının henüz yazdırılıp yazdırılmadığına ilişkin bilgileri depolamak için bu "ev" konumunu kullanabiliriz.
Caf'in versiyonunda, dizide A[i] != i
ilerlerken, A[i]
bunun bir kopya olduğunu ima etti . Benim versiyonumda, biraz farklı bir değişmeze güveniyorum: bu A[i] != i && A[A[i]] == A[i]
, daha önce görmediğimizA[i]
bir kopya olduğunu ima ediyor . ("Daha önce görmediğimiz" bölümünü bırakırsanız, geri kalanı caf değişmez gerçeği ve tüm kopyaların bir ev konumunda bir kopyasına sahip olma garantisi tarafından ima edilmiş olarak görülebilir.) Bu mülk, başlangıç (caf'in 1. döngüsü bittikten sonra) ve aşağıda her adımdan sonra korunduğunu gösteriyorum.
Dizide ilerlerken A[i] != i
, test kısmındaki başarı, daha önce görülmemiş bir kopya A[i]
olabileceğini ima eder . Daha önce görmediysek, o zaman A[i]
ev konumunun kendisine işaret etmesini bekleriz - ikinci yarısında test edilen şey budur.if
durumun . Durum buysa, onu yazdırır ve ev konumunu bu ilk bulunan kopyaya işaret edecek şekilde değiştiririz ve 2 adımlı bir "döngü" oluştururuz.
Bu işlemin değişmezimizi değiştirmediğini görmek m = A[i]
için, belirli bir pozisyonun i
tatmin edici olduğunu varsayalım A[i] != i && A[A[i]] == A[i]
. Yaptığımız değişikliğin ( A[A[i]] = i
), koşullarının m
2. yarısının if
başarısız olmasına neden olarak , diğer ev dışı olayların kopya olarak çıkmasını önlemek için çalışacağı açıktır , ancak i
ev konumuna geldiğinde işe yarayacak m
mı? Evet, çünkü şimdi, bu i
yenide if
koşulun 1. yarısının A[i] != i
doğru olduğunu bulsak da, 2. yarı işaret ettiği konumun bir ev konumu olup olmadığını test eder ve olmadığını bulur. Bu durumda artık olmadığını bilmek m
veya A[m]
yinelenen bir değer, ama biz her iki şekilde biliyoruz,zaten rapor edilmiştirçünkü bu 2 döngü, caf'in 1. döngü sonucunda görünmeyeceği garantilidir. (O m != A[m]
zaman tam olarak biri m
ve A[m]
birden fazla meydana gelirse ve diğerinin hiç meydana gelmediğini unutmayın.)
a[a[i]]
kısıtlamaları çözüme bir miktar ipucu verir - her geçerli dizi değerinin aynı zamanda geçerli bir dizi indeksi olduğu ve O (1) uzay kısıtlamasıswap()
işlemin anahtar olduğuna dair ipuçları verir .