Çok az sayıda döngünüz varsa, burada daha az yer kaplayan, ancak sonlandırılması oldukça uzun süren bir algoritma.
[Düzenle.] Önceki çalışma zamanı analizim, ziyaret ettiğimiz düğümlerin önceden örneklenmiş olanlar arasında olup olmadığının belirlenmesinin önemli maliyetini kaçırdı; bu cevap bunu düzeltmek için bir şekilde revize edilmiştir.
S'nin tüm unsurlarını tekrarlıyoruz . Biz elemanların yörüngelerini keşfettikçe s ∈ S , biz onları tekrar rastlamak olmadığını kontrol edebilmek amacıyla, biz ziyaret ettik düğümlerden tadın. Ayrıca, daha önce ziyaret edilmiş olan ortak bir döngüde (ve dolayısıyla döngülere eşit olan) sona eren yörüngeler birlikleri olan 'bileşenlerden' bir örnek listesini tutarız.
Boş bir bileşen listesi başlatın complist
,. Her bileşen, o bileşenden bir örnek koleksiyonu ile temsil edilir; samples
bazı bileşenler veya diğerleri için örnek olarak seçilen tüm öğeleri saklayan bir arama ağacı da sağlıyoruz. G'nin n'ye kadar bir tamsayı dizisi olmasına izin verin , bunun için üyelik bazı boole yüklemini hesaplayarak verimli bir şekilde belirlenebilir; örneğin, 2 veya mükemmel yetkileri s inci bir tam sayı için güçler p . Her s ∈ S için aşağıdakileri yapın:
- Eğer ler ise
samples
, 5. adıma geçin.
- Boş bir liste
cursample
, yineleyici j ← f ( s ) ve sayaç t ← 1 başlatın .
- İken j değil
samples
:
- Eğer t ∈ G , insert j hem içine cursample
ve samples
.
- t değerini artırın ve j ← f (j) ayarını yapın .
- J'nin olup olmadığını kontrol edin
cursample
. Değilse, daha önce keşfedilmiş bir bileşenle karşılaştık: j bileşenine ait olup olmadığını kontrol eder ve tüm öğelerini artırmak için ilgili cursample
öğeye complist
ekleriz. Aksi takdirde, mevcut yörüngedeki bir öğeyle yeniden karşılaştık, yani daha önce keşfedilen döngülerin herhangi bir temsilcisiyle karşılaşmadan en az bir kez bir döngüyü geçtik: cursample
yeni bulunan bir bileşenden örnek koleksiyonu olarak ekliyoruz complist
.
- Sonraki s ∈ S öğesine ilerleyin .
For n = | S |, X (n) beklenen döngü sayısını ( ör. X (n) = n 1/3 ) açıklayan monoton arttırıcı bir fonksiyon olsun ve Y (n) = y (n) log ( n ) ∈ Ω ( X (n) log ( n )), bellek kullanımı için bir hedef belirleyen monoton arttırıcı bir fonksiyon olabilir ( örn. Y (n) = n 1/2 ). Y (n) ∈ Ω ( X (n) ) gereklidir, çünkü her bileşenden bir örnek depolamak en az X (n) günlük ( n ) alan gerektirir.
Bir yörüngenin ne kadar çok örneğini örneklersek, bir yörüngenin sonunda döngüde bir örneği hızlı bir şekilde seçme ve böylece bu döngüyü hızlı bir şekilde algılama olasılığımız o kadar artar. Bakış bir asimptotikler açısından, daha sonra Belleğimiz sınırları izin pek çok numune olarak elde etmek için mantıklı: biz de ayarlayabilir G , beklenen için y (n) ' den az olan öğeleri n .
- bir yörünge maksimum uzunluğu ise S olması beklenmektedir L biz izin verebilir G tamsayı katları olacak L / y (n) .
- Beklenen uzunluk yoksa, her n / y (n)elementler; bu her durumda örnekler arasındaki aralıklarda bir üst sınırdır.
Yeni bir bileşen ararken, daha önce ziyaret ettiğimiz S öğelerini ( keşfedilen yeni bir bileşenden veya terminal döngüsü zaten bulunan eski bir bileşenden) geçmeye başlarsak , en fazla n / y ( n) önceden örneklenmiş bir elemanla karşılaşma yinelemeleri; bu, o zamana kadar üst sınırdır, her bir yeni bileşen bulma girişimi için artık düğümleri geçiyoruz. Bu tür n denemeler yaptığımızdan, S öğelerini toplamda en fazla n 2 / y (n) kez ziyaret edeceğiz .
Üyeliği test etmek için gereken iş , her ziyarette tekrarladığımız samples
O ( y (n) log y (n) ): bu kontrolün kümülatif maliyeti O ( n 2 log y (n) ). Ayrıca, numuneleri kendi koleksiyonlarına, toplam O ( y (n) log y (n) ) olan toplama maliyeti de vardır . Son olarak, daha önce keşfedilen bir bileşenle her karşılaştığımızda, hangi bileşeni yeniden keşfettiğimizi belirlemek için X (n) log * y (n) zaman harcamalıyız ; bu n defaya kadar olabileceğinden , ilgili kümülatif çalışma nX (n) log y (n) ile sınırlıdır .
Bu nedenle, ziyaret ettiğimiz düğümlerin örnekler arasında olup olmadığını kontrol etmek için yapılan kümülatif çalışma, çalışma süresine hakimdir: bu, O ( n 2 log y (n) ) maliyetidir . O zaman y (n) 'yi mümkün olduğunca küçük yapmalıyız , yani O ( X (n) ).
Böylece, O ( X (n) log ( n )) uzayındaki O ( n 2 log X (n) ) devir sayısı (bu devirlerde biten bileşen sayısıyla aynıdır ) sayılabilir. Bunu yapmak için gereken süre, burada X (n) beklenen döngü sayısıdır.