Yang mengejutkan saya, saya tidak dapat menemukan makalah tentang ini - mungkin mencari kata kunci yang salah.
Jadi, kita punya array apa saja, dan fungsi pada indeksnya; adalah permutasi.f
Bagaimana kita menyusun ulang susunan menurut dengan memori dan runtime sedekat mungkin dengan dan ?
Adakah kondisi tambahan saat tugas ini menjadi lebih mudah? Misal ketika kita secara eksplisit mengetahui fungsi adalah kebalikan dari ?
Saya tahu suatu algoritma yang mengikuti siklus dan melintasi siklus untuk setiap indeks untuk memeriksa apakah itu yang paling sedikit dalam siklusnya, tetapi sekali lagi, ia memiliki waktu proses O (n ^ 2) terburuk , meskipun rata-rata tampaknya berperilaku lebih baik. ...
Jawaban:
Opsi 0: Permuting In Place (1995) oleh Faith E. Fich, J. Ian Munro, Patricio V. Poblete waktu spasi.O ( log 2 n )O ( n logn ) O ( log2n )
Opsi 1: Cheat dengan mengompresi permutasi Anda ke struktur data yang ringkas, lihat Munro http://www.itu.dk/people/ssrao/icalp03-a.pdf .
Opsi 2: Gunakan dekomposisi siklus utama untuk menyimpan perm secara ringkas dan gunakan ruang ekstra itu untuk menipu http://oeis.org/A186202
Opsi 3: Melacak indeks terbesar dari setiap siklus yang dimanipulasi. Untuk setiap iterasi, gunakan indeks tak terlihat terbesar untuk memindahkan segala sesuatu dalam siklusnya satu per satu. Jika itu menyentuh indeks terlihat membatalkan semua yang berhasil karena siklus telah dimanipulasi. waktu, spasi.O ( # siklus ∗ log n )O(n2) O(#cycles∗logn)
Opsi 4: Melacak indeks terbesar dari setiap siklus yang dimanipulasi, tetapi hanya melakukannya dalam kumpulan panjang siklus yang berbeda. Untuk setiap iterasi, gunakan indeks tak terlihat terbesar untuk memindahkan semua yang ada dalam siklusnya satu per satu. Jika itu menyentuh indeks terlihat membatalkan semua yang berhasil karena siklus sudah dimanipulasi. waktu, spasi.O ( ( # siklus _ dengan _ yang sama _ ukuran ) * log n )O(n2∗distinct_cycle_lengths) O((#cycles_with_same_size)∗logn)
Opsi 5: Dari makalah yang sama oleh Munro sebagai Opsi 0, Untuk putar siklus jika adalah indeks terbesar dalam siklus itu. waktu dan ruang.p ( i ) i O ( n 2 ) O ( log n )i=1..n p(i) i O(n2) O(logn)
sumber
Jika Anda menggunakan representasi siklus permutasi, Anda memerlukan 1 elemen array tambahan untuk menyimpan item yang sedang diijinkan dan Anda dapat menjalankan siklus di operasi O (N) yang lebih buruk.
sumber
Setiap permutasi dari item N dapat dikonversi ke permutasi lainnya menggunakan N-1 atau lebih sedikit pertukaran. Kasus terburuk untuk metode ini dapat memerlukan panggilan O (n ^ 2) ke oracle Anda, F (). Mulai dari posisi paling tidak. Biarkan x menjadi posisi yang saat ini kami tukar.
Jika F (x)> = x maka tukar posisi x dan F (x). Selain itu, kita harus menemukan di mana item yang berada di posisi F (x) saat ini ada dalam daftar. Kita bisa melakukan ini dengan iterasi berikut. Biarkan y = F (x). Lakukan sampai y> = x: y = F (y): End Do. Sekarang tukar posisi x dan y.
sumber
Metode ini menggunakan kebalikan dari F dan membutuhkan n bit penyimpanan. Jika x adalah posisi item dalam array asli, misalkan G (x) menjadi posisi item dalam array yang diurutkan. Biarkan B menjadi array n bit. Setel semua n bit B ke 0.
UNTUK x = 1 hingga n-1: JIKA B (x) == 0 KEMUDIAN: y = G (x): LAKUKAN SAMPAI x == y: Tukar posisi x dan y: B (y) = 1: y = G ( y): LOOP: ENDIF: BERIKUTNYA X
Metode ini terus menukar item saat ini di posisi x ke posisi akhir item. Loop dalam berakhir ketika item yang benar ditukar ke posisi x. Karena setiap swap memindahkan setidaknya satu item ke posisi akhir item, loop Do dalam tidak dapat mengeluarkan lebih dari n-1 kali selama menjalankan. Saya pikir metode ini adalah O (n) waktu dan ruang.
sumber