Apakah ada algoritma waktu riffle shuffle linear waktu? Ini adalah algoritma yang mampu dilakukan oleh beberapa tangan yang sangat tangkas: membagi array input berukuran rata, dan kemudian menyatukan elemen dari dua bagian.
Mathworld memiliki halaman singkat tentang riffle shuffle . Secara khusus, saya tertarik pada variasi out-shuffle yang mengubah array input 1 2 3 4 5 6 menjadi 1 4 2 5 3 6. Perhatikan bahwa dalam definisi mereka, panjang input adalah .
Ini mudah untuk melakukan ini dalam waktu linier jika kita punya array kedua ukuran atau lebih berguna. Pertama-tama salin elemen terakhir ke array. Kemudian, dengan asumsi pengindeksan berbasis 0, salin elemen pertama dari indeks ke . Kemudian salin elemen dari array kedua kembali ke array input, pemetaan indeks ke . (Kita dapat melakukan pekerjaan sedikit lebih sedikit dari itu, karena elemen pertama dan terakhir dalam input tidak bergerak.)n n [ 0 , 1 , 2 , . . . , N - 1 ] [ 0 , 2 , 4 , . . . , 2 n - 2 ] n [ 0 , 1 , 2 , . . . , N - 1 ] [ 1 , 3 , 5 , . . . ,
Salah satu cara untuk melakukan hal ini di tempat melibatkan dekomposisi permutasi menjadi siklus terpisah, dan kemudian mengatur ulang elemen sesuai dengan setiap siklus. Sekali lagi, dengan asumsi pengindeksan berbasis 0, permutasi yang terlibat dalam kasus 6 elemen adalah
Seperti yang diharapkan, elemen pertama dan terakhir adalah poin tetap, dan jika kita mengubah 4 elemen tengah kita mendapatkan hasil yang diharapkan.
Sayangnya, pemahaman saya tentang matematika permutasi (dan L mereka ) sebagian besar didasarkan pada wikipedia, dan saya tidak tahu apakah ini dapat dilakukan dalam waktu linier. Mungkin permutasi yang terlibat dalam pengocokan ini dapat dengan cepat terurai? Juga, kita bahkan tidak perlu dekomposisi lengkap. Cukup menentukan satu elemen saja dari masing-masing siklus disjoint akan cukup, karena kita dapat merekonstruksi siklus dari salah satu elemennya. Mungkin diperlukan pendekatan yang sangat berbeda.
Sumber daya yang baik pada matematika terkait sama berharganya dengan algoritma. Terima kasih!
Jawaban:
Masalahnya secara mengejutkan adalah non-sepele. Ini adalah solusi yang bagus dari Ellis dan Markov, In-Situ, Stable Merging melalui Perfect Shuffle (bagian 7). Ellis, Krahn dan Fan, Menghitung Siklus dalam Permutasi Acak Sempurna berhasil memilih "pemimpin siklus", dengan mengorbankan lebih banyak memori. Juga terkait adalah kertas bagus oleh Fich, Munro dan Poblete, Permuting In Place , yang memberikan algoritma waktu umum untuk model oracle. Jika hanya sebuah oracle untuk permutasi tersedia, algoritma membutuhkan ruang logaritmik; jika kita juga memiliki oracle untuk kebalikannya, itu membutuhkan ruang yang konstan.O(nlogn)
Sekarang untuk solusi Ellis dan Markov. Pertama, misalkan . Kemudian menghitung acak shuffle pesanan dan mengurangi untuk menghitung acak shuffle pesanan x dan y , dengan rotasi sebelumnya. Berikut ini adalah bukti dengan contoh ( n = 5 , x = 3 , y = 2 ): 012 345 67 89 012 567 34 89 051627 3849n=x+y n x y n=5 x=3 y=2
Ellis dan Markov menemukan cara mudah untuk menghitung shuffle sempurna ketika , menggunakan ruang konstan dan waktu linier. Dengan menggunakan ini, kami memperoleh algoritma untuk menghitung shuffle sempurna untuk arbitrary n . Pertama, menulis n = 2 k 0 + ⋯ + 2 k w menggunakan pengkodean biner dari n , dan biarkan n i = 2 k i + ⋯ + 2 k w . Putar tengah n 0 bit, kocok 2 k kanann=2k n n=2k0+⋯+2kw n ni=2ki+⋯+2kw n0 bit. Mengabaikanbitkanan2 k 0 bit, putar tengahn1bit, dan kocok bit kanan2 k 1 . Dan seterusnya. Perhatikan bahwa rotasi mudah karena beberapa elemen pertama yang diputar berfungsi sebagai pemimpin siklus. Kompleksitas total rotasi adalahO(n0+⋯+nw)=O(n), karenan t + 1 <nt/2. Kompleksitas total dari shuffles bagian dalam adalahO(2k0 2k0 n1 2k1 O(n0+⋯+nw)=O(n) nt+1<nt/2 .O(2k0+⋯+2kw)=O(n)
Tetap menunjukkan bagaimana menghitung shuffle sempurna ketika . Bahkan, kita akan dapat mengidentifikasi pemimpin siklus, berikut karya klasik pada kalung (Fredricksen dan Maiorana, Kalung manik-manik di k warna dan k -ary de urutan Bruijn ; Fredricksen dan Kessler, Sebuah algoritma untuk menghasilkan kalung dari manik-manik dalam dua warna ).n=2k k k
Apa hubungannya? Saya mengklaim bahwa permutasi shuffle sesuai dengan pergeseran kanan representasi biner. Berikut ini adalah bukti dengan contoh, untuk : 000 001 010 011 100 101 110 111 000 100 001 101 010 110 011 111 Oleh karena itu, untuk menemukan pemimpin siklus, kita perlu menemukan satu perwakilan dari setiap kelas ekivalensi dari rotasi string biner dengan panjang k . Makalah yang disebutkan di atas memberikan algoritma berikut untuk menghasilkan semua pemimpin siklus. Mulai dengan 0 kn=8
Misalnya, ketika ini menghasilkan urutan 0000 , 0001 , 0010 , 0011 , 0101 , 0110 , 0111 , 1111 .n=16
Pemimpin siklus disorot.
sumber
Ini adalah pertanyaan awal di cs.stackexchange.com dan jawabannya ada di sini: /cs/332/in-place-algorithm-for-interleaving-an-array/400#400
Ini adalah penjelasan dari makalah ini: http://arxiv.org/abs/0805.1598 .
sumber
Apa yang terjadi jika Anda menuliskan fungsi riffle shuffle? Jikam adalah panjang dari total array, mis n = m - 2 menjadi panjang array setelah menghapus elemen pertama dan terakhir. Kemudian diacak indeks indeksnyasaya adalah f( i ) = 2 ⋅ i jika i ≤ n / 2 dan f( i ) = 2 ⋅ ( imodn / 2 ) - 1 jika i > n / 2 . Kemudian Anda bisa "pointer jump" melalui array, bertukar dengan menerapkan kembali fungsi.
Dengan asumsi akses acak, ini akan menjadi waktu linear sambil memerlukanO ( 1 ) kata-kata tambahan (untuk menyimpan nilai array pada indeks yang diberikan), dan sebagainya O ( logn ) ruang ekstra.
sumber