Katakanlah saya memiliki daftar n elemen, saya tahu ada n! cara yang mungkin untuk memesan elemen ini. Apa algoritma untuk menghasilkan semua kemungkinan urutan daftar ini? Contoh, saya punya daftar [a, b, c]. Algoritme akan mengembalikan [[a, b, c], [a, c, b,], [b, a, c], [b, c, a], [c, a, b], [c, b , Sebuah]].
Saya membaca ini di sini http://en.wikipedia.org/wiki/Permutation#Algorithms_to_generate_permutations
Tapi Wikipedia tidak pernah pandai menjelaskan. Saya tidak mengerti banyak tentang itu.
algorithm
list
permutation
fent
sumber
sumber
Jawaban:
Pada dasarnya, untuk setiap item dari kiri ke kanan, semua permutasi item yang tersisa dibuat (dan masing-masing ditambahkan dengan elemen saat ini). Ini dapat dilakukan secara rekursif (atau secara berulang jika Anda suka nyeri) sampai item terakhir tercapai di mana hanya ada satu urutan yang memungkinkan.
Jadi dengan daftar [1,2,3,4] semua permutasi yang dimulai dengan 1 dibuat, lalu semua permutasi yang dimulai dengan 2, lalu 3 lalu 4.
Ini secara efektif mengurangi masalah dari salah satu menemukan permutasi dari daftar empat item menjadi daftar tiga item. Setelah dikurangi menjadi 2 dan kemudian 1 daftar item, semuanya akan ditemukan.
Contoh yang menunjukkan permutasi proses menggunakan 3 bola berwarna:
(dari https://en.wikipedia.org/wiki/Permutation#/media/File:Permutations_RGB.svg - https://commons.wikimedia.org/wiki/File:Permutations_RGB. svg )
sumber
Berikut adalah algoritma dalam Python yang bekerja di tempat pada sebuah array:
Anda dapat mencoba kode sendiri di sini: http://repl.it/J9v
sumber
Sudah ada banyak solusi bagus di sini, tetapi saya ingin berbagi bagaimana saya menyelesaikan masalah ini sendiri dan berharap ini dapat membantu seseorang yang juga ingin mendapatkan solusinya sendiri.
Setelah merenungkan masalah tersebut, saya mendapatkan dua kesimpulan berikut:
L
ukurann
akan ada jumlah solusi yang sama dimulai dengan L 1 , L 2 ... L n elemen daftar. Karena total adan!
permutasi daftar ukurann
, kami mendapatkann! / n = (n-1)!
permutasi di setiap grup.[a,b]
dan[b,a]
.Dengan menggunakan dua ide sederhana ini, saya memperoleh algoritme berikut:
Berikut adalah bagaimana saya menerapkan ini di C #:
sumber
Bagi saya, jawaban Wikipedia untuk "urutan leksikografik" tampak sangat eksplisit dalam gaya buku masak. Ini mengutip asal abad ke-14 untuk algoritme!
Saya baru saja menulis implementasi cepat di Java dari algoritma Wikipedia sebagai cek dan tidak ada masalah. Tapi apa yang Anda miliki di Q Anda sebagai contoh BUKAN "daftar semua permutasi", tetapi "DAFTAR semua permutasi", jadi wikipedia tidak akan banyak membantu Anda. Anda memerlukan bahasa di mana daftar permutasi dapat dibuat dengan layak. Dan percayalah, daftar yang panjangnya beberapa miliar biasanya tidak ditangani dalam bahasa-bahasa penting. Anda benar-benar menginginkan bahasa pemrograman fungsional non-ketat, di mana daftar adalah objek kelas satu, untuk mengeluarkan barang-barang tanpa membawa mesin mendekati kematian panas Semesta.
Itu mudah. Dalam Haskell standar atau bahasa FP modern lainnya:
dan
sumber
Seperti yang dikatakan WhirlWind, Anda mulai dari awal.
Anda menukar kursor dengan setiap nilai yang tersisa, termasuk kursor itu sendiri, ini semua adalah contoh baru (saya menggunakan
int[]
danarray.clone()
dalam contoh).Kemudian lakukan permutasi pada semua daftar yang berbeda ini, pastikan kursor berada di kanan.
Jika tidak ada lagi nilai yang tersisa (kursor berada di ujung), cetak daftar. Ini adalah kondisi berhenti.
sumber
Rekursif selalu membutuhkan usaha mental untuk mempertahankannya. Dan untuk bilangan besar, faktorial mudah besar dan stack overflow dengan mudah menjadi masalah.
Untuk bilangan kecil (3 atau 4, yang paling sering ditemui), beberapa loop cukup sederhana dan lurus ke depan. Sayangnya, jawaban dengan loop tidak dipilih.
Mari kita mulai dengan enumerasi (bukan permutasi). Cukup baca kode tersebut sebagai kode perl semu.
Enumeration lebih sering dijumpai daripada permutasi, tetapi jika permutasi dibutuhkan, tambahkan saja ketentuannya:
Sekarang jika Anda benar-benar membutuhkan metode umum yang berpotensi untuk daftar besar, kita dapat menggunakan metode radix. Pertama, pertimbangkan masalah pencacahan:
Kenaikan radix pada dasarnya adalah penghitungan angka (dalam dasar jumlah elemen daftar).
Sekarang jika Anda membutuhkan permutaion, cukup tambahkan cek di dalam loop:
Edit: Kode di atas seharusnya berfungsi, tetapi untuk permutasi, radix_increment bisa jadi boros. Jadi jika waktu adalah masalah praktis, kita harus mengubah radix_increment menjadi permute_inc:
Tentu saja sekarang kode ini secara logika lebih kompleks, saya akan tinggalkan untuk latihan pembaca.
sumber
Referensi: Geeksforgeeks.org
sumber
Jika ada yang bertanya-tanya bagaimana melakukan permutasi di javascript.
Ide / pseudocode
sebagai contoh. 'a' + permute (bc). permute dari bc akan menjadi bc & cb. Sekarang tambahkan keduanya akan menghasilkan abc, acb. Demikian pula, pilih b + permute (ac) akan menyediakan bac, bca ... dan terus berjalan.
sekarang lihat kodenya
Luangkan waktu Anda untuk memahami ini. Saya mendapat kode ini dari ( pertumation in JavaScript )
sumber
Satu lagi di Python, tidak ditempatkan sebagai @ cdiggins, tapi saya pikir itu lebih mudah untuk dipahami
sumber
Saya berpikir untuk menulis kode untuk mendapatkan permutasi dari bilangan bulat yang diberikan dengan ukuran berapa pun, yaitu, dengan memberikan angka 4567, kami mendapatkan semua kemungkinan permutasi hingga 7654 ... Jadi saya mengerjakannya dan menemukan algoritme dan akhirnya menerapkannya, Di sini adalah kode yang tertulis dalam "c". Anda cukup menyalinnya dan menjalankannya di kompiler open source apa pun. Tetapi beberapa kekurangan menunggu untuk di-debug. Mohon hargai.
Kode:
sumber
Saya membuat yang ini. berdasarkan penelitian terlalu permutate (qwe, 0, qwe.length-1); Asal tahu saja, Anda bisa melakukannya dengan atau tanpa mundur
sumber
Berikut adalah metode mainan Ruby yang berfungsi seperti
#permutation.to_a
itu mungkin lebih terbaca oleh orang gila. Ini sangat lambat, tetapi juga 5 baris.sumber
Saya telah menulis solusi rekursif ini di ANSI C. Setiap eksekusi fungsi Permutasi menyediakan satu permutasi berbeda sampai semuanya selesai. Variabel global juga dapat digunakan untuk variabel fakta dan hitungan.
sumber
Versi Java
Misalnya
keluaran:
sumber
di PHP
sumber
Berikut adalah kode dengan Python untuk mencetak semua kemungkinan permutasi dari daftar:
Saya telah menggunakan algoritme urutan leksikografik untuk mendapatkan semua kemungkinan permutasi, tetapi algoritme rekursif lebih efisien. Anda dapat menemukan kode untuk algoritma rekursif di sini: Permutasi rekursi Python
sumber
sumber
Di Scala
sumber
ini adalah versi java untuk permutasi
sumber
Berikut adalah implementasi untuk ColdFusion (memerlukan CF10 karena argumen penggabungan ke ArrayAppend ()):
Berdasarkan solusi js KhanSharp di atas.
sumber
Saya tahu ini sangat sangat tua dan bahkan di luar topik dalam stackoverflow hari ini, tetapi saya masih ingin memberikan jawaban javascript yang ramah untuk alasan sederhana yang berjalan di browser Anda.
Saya juga telah menambahkan titik
debugger
putus direktif sehingga Anda dapat melangkah melalui kode (diperlukan chrome) untuk melihat cara kerja algoritma ini. Buka konsol dev Anda di chrome (F12
di windows atauCMD + OPTION + I
di mac) lalu klik "Jalankan cuplikan kode". Ini mengimplementasikan algoritme yang persis sama dengan yang disajikan @WhirlWind dalam jawabannya.Browser Anda harus menghentikan sementara eksekusi sesuai
debugger
petunjuk. GunakanF8
untuk melanjutkan eksekusi kode.Telusuri kode dan lihat cara kerjanya!
sumber
Dalam solusi Java berikut, kami memanfaatkan fakta bahwa Strings tidak dapat diubah untuk menghindari kloning set hasil pada setiap iterasi.
Inputnya adalah String, katakan "abc", dan outputnya adalah semua kemungkinan permutasi:
Kode:
Pendekatan yang sama dapat diterapkan ke array (bukan string):
sumber
Ini solusi saya di Java:
sumber
Anda tidak dapat benar-benar berbicara tentang memecahkan masalah permultation dalam rekursi tanpa memposting implementasi dalam bahasa (dialek) yang memelopori ide tersebut . Nah, demi kelengkapan berikut ini salah satu cara yang bisa dilakukan di Scheme.
menelepon
(permof (list "foo" "bar" "baz"))
kami akan mendapatkan:Saya tidak akan membahas detail algoritme karena sudah cukup dijelaskan di posting lain. Idenya sama.
Namun, masalah rekursif cenderung lebih sulit untuk dimodelkan dan dipikirkan dalam medium destruktif seperti Python, C, dan Java, sedangkan di Lisp atau ML dapat diekspresikan secara ringkas.
sumber
Berikut adalah solusi rekursif di PHP. Postingan WhirlWind mendeskripsikan logika secara akurat. Perlu disebutkan bahwa membuat semua permutasi berjalan dalam waktu faktorial, jadi sebaiknya gunakan pendekatan berulang sebagai gantinya.
Fungsi strDiff mengambil dua string,
s1
dans2
, dan mengembalikan string baru dengan semua yang ada di dalamnyas1
tanpa elemen dis2
(materi duplikat). Jadi,strDiff('finish','i')
=>'fnish'
('i' kedua tidak dihapus).sumber
Berikut adalah algoritma di R, jika ada yang perlu menghindari memuat pustaka tambahan seperti yang harus saya lakukan.
Contoh penggunaan:
sumber
sumber
Ini adalah kode rekursif untuk java, idenya adalah memiliki awalan yang menambahkan sisa karakter:
Contoh:
Masukan = "ABC"; Keluaran:
ABC ACB BAC BCA CAB CBA
sumber
str
saat memanggil secara rekursif, jika tidak maka tidak akan berhenti.Sekadar lengkap, C ++
...
sumber
Berikut adalah solusi non-rekursif dalam C ++ yang menyediakan permutasi berikutnya dalam urutan menaik, mirip dengan fungsionalitas yang disediakan oleh std :: next_permutation:
sumber