Jika Anda memiliki sangat sedikit siklus, inilah algoritma yang akan menggunakan lebih sedikit ruang, tetapi membutuhkan waktu lebih lama untuk berhenti.
[Sunting.] Analisis run-time saya sebelumnya melewatkan biaya penting untuk menentukan apakah node yang kami kunjungi adalah di antara yang sebelumnya diambil sampel; jawaban ini agak direvisi untuk memperbaikinya.
Kita lagi iterate melalui semua elemen S . Saat kami menjelajahi orbit elemen s ∈ S , kami mengambil sampel dari node yang telah kami kunjungi, agar dapat memeriksa apakah kami menemukan mereka lagi. Kami juga memelihara daftar sampel dari 'komponen' - serikat orbit yang berakhir dalam siklus umum (dan karenanya sama dengan siklus) - yang sebelumnya telah dikunjungi.
Inisialisasi daftar komponen yang kosong complist
,. Setiap komponen diwakili oleh kumpulan sampel dari komponen itu; kami juga memelihara pohon pencarian samples
yang menyimpan semua elemen yang telah dipilih sebagai sampel untuk beberapa komponen atau lainnya. Biarkan G menjadi urutan bilangan bulat hingga n , yang keanggotaannya ditentukan secara efisien dengan menghitung beberapa predikat boolean; misalnya, kekuatan dari 2 atau sempurna p th kekuatan untuk suatu bilangan bulat p . Untuk setiap s ∈ S , lakukan hal berikut:
- Jika s ada di
samples
, lewati ke langkah # 5.
- Inisialisasi daftar kosong
cursample
, sebuah iterator j ← f ( s ), dan penghitung t ← 1.
- Saat j tidak ada di
samples
:
- Jika t ∈ G , masukkan j ke dalam keduanya cursample
dan samples
.
- Kenaikan t dan atur j ← f (j) .
- Periksa untuk melihat apakah j ada di
cursample
. Jika tidak, kami telah menemukan komponen yang telah dieksplorasi sebelumnya: kami memeriksa komponen mana yang termasuk j , dan memasukkan semua elemen cursample
ke dalam elemen yang sesuai complist
untuk menambahnya. Jika tidak, kami telah menemukan kembali elemen dari orbit saat ini, yang berarti bahwa kami telah melintasi siklus setidaknya sekali tanpa menemui perwakilan dari siklus yang sebelumnya ditemukan: kami memasukkan cursample
, sebagai kumpulan sampel dari komponen yang baru ditemukan, ke complist
.
- Lanjutkan ke elemen berikutnya s ∈ S .
Untuk n = | S |, misalkan X (n) adalah fungsi peningkatan monoton yang menggambarkan jumlah siklus yang diharapkan ( mis. X (n) = n 1/3 ), dan misalkan Y (n) = y (n) log ( n ) ∈ Ω ( X (n) log ( n )) adalah fungsi yang meningkatkan monoton menentukan target untuk penggunaan memori ( misalnya y (n) = n 1/2 ). Kami memerlukan y (n) ∈ Ω ( X (n) ) karena akan membutuhkan setidaknya X (n) log ( n ) ruang untuk menyimpan satu sampel dari setiap komponen.
Semakin banyak elemen dari orbit yang kita sampel, semakin besar kemungkinan kita untuk dengan cepat memilih sampel dalam siklus di akhir orbit, dan dengan demikian dengan cepat mendeteksi siklus itu. Dari sudut pandang asimptotik, masuk akal untuk mendapatkan sampel sebanyak yang diizinkan oleh ingatan kita: kita mungkin juga menetapkan G untuk memiliki elemen y (n) yang diharapkan yang kurang dari n .
- Jika panjang maksimum orbit di S diharapkan L , kami dapat membiarkan G menjadi kelipatan bilangan bulat L / y (n) .
- Jika tidak ada panjang yang diharapkan, kami cukup sampel satu kali setiap n / y (n)elemen; ini dalam hal apapun merupakan batas atas pada interval antar sampel.
Jika, dalam mencari komponen baru, kita mulai melintasi elemen S yang sebelumnya telah kita kunjungi (baik dari komponen baru yang ditemukan atau yang lama yang siklus terminalnya telah ditemukan), itu akan memakan waktu paling banyak n / y ( n) iterasi untuk menemukan elemen yang sebelumnya diambil sampelnya; ini kemudian merupakan batas atas pada berapa kali, untuk setiap upaya untuk menemukan komponen baru, kami melintasi node yang berlebihan. Karena kita membuat n upaya tersebut, kita kemudian akan berlebihan mengunjungi unsur S paling n 2 / y (n) kali secara total.
Pekerjaan yang diperlukan untuk menguji keanggotaan samples
adalah O ( y (n) log y (n) ), yang kami ulangi pada setiap kunjungan: biaya kumulatif pemeriksaan ini adalah O ( n 2 log y (n) ). Ada juga biaya untuk menambahkan sampel ke koleksi masing-masing, yang secara kumulatif adalah O ( y (n) log y (n) ). Akhirnya, setiap kali kita menemukan kembali komponen yang ditemukan sebelumnya, kita harus mengeluarkan hingga X (n) log * y (n) waktu untuk menentukan komponen mana yang kita temukan kembali; karena hal ini dapat terjadi hingga n kali, pekerjaan kumulatif yang terlibat dibatasi oleh n X (n) log y (n) .
Dengan demikian, pekerjaan kumulatif yang dilakukan dalam memeriksa apakah node yang kami kunjungi adalah di antara sampel yang mendominasi run-time: ini biaya O ( n 2 log y (n) ). Maka kita harus membuat y (n) sekecil mungkin, yaitu O ( X (n) ).
Jadi, seseorang dapat menghitung jumlah siklus (yang sama dengan jumlah komponen yang berakhir pada siklus tersebut) dalam ruang O ( X (n) log ( n )), mengambil O ( n 2 log X (n) ) waktu untuk melakukannya, di mana X (n) adalah jumlah siklus yang diharapkan.