Menghasilkan semua permutasi dari string yang diberikan
418
Apa cara yang elegan untuk menemukan semua permutasi string. Misalnya permutasi untuk ba, akan badan ab, tetapi bagaimana dengan string yang lebih panjang seperti abcdefgh? Apakah ada contoh implementasi Java?
Ada asumsi yang perlu disebutkan. Karakternya unik. Misalnya, untuk String "aaaa" hanya ada satu jawaban. Untuk mendapatkan jawaban yang lebih umum, Anda dapat menyimpan string dalam satu set untuk menghindari duplikasi
Afshin Moazami
1
Apakah pengulangan karakter diperbolehkan, atau pengulangan karakter tidak diperbolehkan? Bisakah satu string memiliki beberapa kejadian dengan karakter yang sama?
Anderson Green
2
Baca teorinya (atau jika, seperti saya, Anda malas, buka en.wikipedia.org/wiki/Permutation ) dan terapkan algoritma yang nyata. Pada dasarnya Anda dapat membuat urutan urutan elemen (fakta bahwa string tidak relevan) dan berjalan melalui urutan sampai Anda kembali ke awal. Hindari segala sesuatu yang melibatkan rekursi atau manipulasi string.
CurtainDog
Jawaban:
601
publicstaticvoid permutation(String str){
permutation("", str);}privatestaticvoid permutation(String prefix,String str){int n = str.length();if(n ==0)System.out.println(prefix);else{for(int i =0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i)+ str.substring(i+1, n));}}
Itu bukan ilmu roket, saya datang dengan jawaban yang hampir sama. Tweak kecil: alih-alih berulang sampai n==0, Anda dapat menghentikan level sebelumnya pada n==1dan mencetak prefix + str.
lambshaanxy
7
"Apa kompleksitas waktu dan ruang dari ini?" tanpa semacam jawaban parsial caching algoritma apa pun yang menghasilkan permutasi adalah o (n!) karena hasil yang ditetapkan untuk pertanyaan permutasi adalah faktorial untuk input.
jeremyjjbrown
9
Elegan, ya. Tetapi solusi yang mengkonversi ke array char dan swap untuk menghasilkan permutasi akan membutuhkan lebih sedikit menyalin dan menghasilkan lebih sedikit sampah. Algoritma ini juga gagal memperhitungkan karakter yang berulang.
Gene
20
@AfshinMoazami saya pikir str.substring (i +1, n) dapat diganti dengan str.substring (i +1). Menggunakan str.substring (i) akan menyebabkan java.lang.StackOverflowError.
Ayusman
196
Gunakan rekursi.
Coba masing-masing huruf pada gilirannya sebagai huruf pertama dan kemudian temukan semua permutasi dari huruf yang tersisa menggunakan panggilan rekursif.
Kasus dasar adalah ketika input adalah string kosong, satu-satunya permutasi adalah string kosong.
Bagaimana Anda bisa menambahkan tipe kembali ke metode permute? kompiler tidak dapat menentukan tipe kembalinya metode ini di setiap iterasi, meskipun itu jelas merupakan tipe String.
user1712095
Bagaimana Anda memastikan permutasi yang berbeda dalam metode ini?
kapad
70
Inilah solusi saya yang didasarkan pada gagasan buku "Cracking the Coding Wawancara" (P54):
/**
* List permutations of a string.
*
* @param s the input string
* @return the list of permutations
*/publicstaticArrayList<String> permutation(String s){// The resultArrayList<String> res =newArrayList<String>();// If input string's length is 1, return {s}if(s.length()==1){
res.add(s);}elseif(s.length()>1){int lastIndex = s.length()-1;// Find out the last characterString last = s.substring(lastIndex);// Rest of the stringString rest = s.substring(0, lastIndex);// Perform permutation on the rest string and// merge with the last character
res = merge(permutation(rest), last);}return res;}/**
* @param list a result of permutation, e.g. {"ab", "ba"}
* @param c the last character
* @return a merged new list, e.g. {"cab", "acb" ... }
*/publicstaticArrayList<String> merge(ArrayList<String> list,String c){ArrayList<String> res =newArrayList<>();// Loop through all the string in the listfor(String s : list){// For each string, insert the last character to all possible positions// and add them to the new listfor(int i =0; i <= s.length();++i){String ps =newStringBuffer(s).insert(i, c).toString();
res.add(ps);}}return res;}
Halaman (71) dalam Cracking the Coding Wawancara Buku, Edisi 6. :)
KarimIhab
5
Apakah ini benar-benar solusi yang baik? Itu bergantung pada menyimpan hasil dalam daftar, oleh karena itu untuk string input pendek itu tumbuh di luar kendali.
Androrider
apa yang dilakukan merger?
Basavaraj Walikar
Ini memasukkan c di setiap posisi yang mungkin dari setiap string dalam daftar jadi jika daftar hanya berisi ["b"] dan c adalah "a" hasil penggabungan adalah ["ab", "ba"] di sini solusi yang sama dengan Swift gist.github. com / daniaDlbani / 3bc10e02541f9ba310d546040c5322fc
Dania Delbani
53
Dari semua solusi yang diberikan di sini dan di forum lain, saya paling suka Mark Byers. Deskripsi itu sebenarnya membuat saya berpikir dan mengkodekannya sendiri. Sayang sekali saya tidak bisa memilih solusinya karena saya pemula.
Bagaimanapun di sini adalah implementasi dari deskripsinya
publicclassPermTest{publicstaticvoid main(String[] args)throwsException{String str ="abcdef";StringBuffer strBuf =newStringBuffer(str);
doPerm(strBuf,0);}privatestaticvoid doPerm(StringBuffer str,int index){if(index == str.length())System.out.println(str);else{//recursively solve this by placing all other chars at current first pos
doPerm(str, index+1);for(int i = index+1; i < str.length(); i++){//start swapping all other chars with current first char
swap(str,index, i);
doPerm(str, index+1);
swap(str,i, index);//restore back my string buffer}}}privatestaticvoid swap(StringBuffer str,int pos1,int pos2){char t1 = str.charAt(pos1);
str.setCharAt(pos1, str.charAt(pos2));
str.setCharAt(pos2, t1);}}
Saya lebih suka solusi ini daripada yang pertama di utas ini karena solusi ini menggunakan StringBuffer. Saya tidak akan mengatakan solusi saya tidak membuat string sementara (itu sebenarnya tidak di system.out.printlnmana toString()StringBuffer dipanggil). Tapi saya hanya merasa ini lebih baik daripada solusi pertama di mana terlalu banyak string literal dibuat. Mungkin ada orang kinerja di luar sana yang dapat mengevaluasi ini dalam hal 'memori' (untuk 'waktu' itu sudah terlambat karena 'swap' tambahan)
Mengapa tidak hanya melakukan if(index == str.length())dan doPerm(str, index + 1);? The currPostampaknya tidak perlu di sini.
Robur_131
Maaf, bisakah Anda menjelaskan lebih lanjut tentang pertanyaan itu? Apakah Anda hanya menyarankan untuk tidak menggunakan variabel arus ekstra (digunakan karena beberapa kejadian dan juga keterbacaan) jika tidak silakan tempelkan solusi yang Anda sarankan untuk melihat
srikanth yaradla
Ah saya mengerti maksud Anda adalah perubahan pada kondisi dasar dengan pengindeksan ke depan. Bekerja dengan baik. Hanya saja solusi yang saya sajikan sebagian besar dipengaruhi oleh kemudian solusi lain yang sering melewati string terpotong daripada yang asli (yang mana 0 masuk akal). Namun demikian terima kasih telah menunjuk. Akan melihat apakah saya dapat mengedit, sudah bertahun-tahun sejak saya masuk ke situs ini.
srikanth yaradla
22
Solusi yang sangat mendasar di Jawa adalah dengan menggunakan rekursi + Set (untuk menghindari pengulangan) jika Anda ingin menyimpan dan mengembalikan string solusi:
publicstaticSet<String> generatePerm(String input){Set<String> set =newHashSet<String>();if(input =="")return set;Character a = input.charAt(0);if(input.length()>1){
input = input.substring(1);Set<String> permSet = generatePerm(input);for(String x : permSet){for(int i =0; i <= x.length(); i++){
set.add(x.substring(0, i)+ a + x.substring(i));}}}else{
set.add(a +"");}return set;}
@ashisahu O (n!) karena kita punya n! permutasi dalam string n panjang yang diberikan.
Zok
17
Semua kontributor sebelumnya telah melakukan pekerjaan yang hebat menjelaskan dan menyediakan kode. Saya pikir saya harus membagikan pendekatan ini juga karena mungkin membantu seseorang juga. Solusinya didasarkan pada ( algoritma heaps ' )
Beberapa barang:
Perhatikan item terakhir yang digambarkan dalam excel hanya untuk membantu Anda memvisualisasikan logika dengan lebih baik. Jadi, nilai aktual pada kolom terakhir adalah 2,1,0 (jika kita menjalankan kode karena kita berurusan dengan array dan array mulai dengan 0).
Algoritma swapping terjadi berdasarkan nilai genap atau ganjil dari posisi saat ini. Ini sangat jelas jika Anda melihat di mana metode swap dipanggil. Anda dapat melihat apa yang terjadi.
Inilah yang terjadi:
publicstaticvoid main(String[] args){String ourword ="abc";String[] ourArray = ourword.split("");
permute(ourArray, ourArray.length);}privatestaticvoid swap(String[] ourarray,int right,int left){String temp = ourarray[right];
ourarray[right]= ourarray[left];
ourarray[left]= temp;}publicstaticvoid permute(String[] ourArray,int currentPosition){if(currentPosition ==1){System.out.println(Arrays.toString(ourArray));}else{for(int i =0; i < currentPosition; i++){// subtract one from the last position (here is where you are// selecting the the next last item
permute(ourArray, currentPosition -1);// if it's odd positionif(currentPosition %2==1){
swap(ourArray,0, currentPosition -1);}else{
swap(ourArray, i, currentPosition -1);}}}}
publicstaticvoid permute(String s){if(null==s || s.isEmpty()){return;}// List containing words formed in each iteration List<String> strings =newLinkedList<String>();
strings.add(String.valueOf(s.charAt(0)));// add the first element to the list// Temp list that holds the set of strings for // appending the current character to all position in each word in the original listList<String> tempList =newLinkedList<String>();for(int i=1; i< s.length(); i++){for(int j=0; j<strings.size(); j++){
tempList.addAll(merge(s.charAt(i), strings.get(j)));}
strings.removeAll(strings);
strings.addAll(tempList);
tempList.removeAll(tempList);}for(int i=0; i<strings.size(); i++){System.out.println(strings.get(i));}}/**
* helper method that appends the given character at each position in the given string
* and returns a set of such modified strings
* - set removes duplicates if any(in case a character is repeated)
*/privatestaticSet<String> merge(Character c,String s){if(s==null|| s.isEmpty()){returnnull;}int len = s.length();StringBuilder sb =newStringBuilder();Set<String> list =newHashSet<String>();for(int i=0; i<= len; i++){
sb =newStringBuilder();
sb.append(s.substring(0, i)+ c + s.substring(i, len));
list.add(sb.toString());}return list;}
solusi ini tampaknya salah System.out.println(permute("AABBC").size());menampilkan 45, tetapi sebenarnya 5! = 120
Mladen Adamovic
11
Mari kita gunakan input abcsebagai contoh.
Mulailah hanya dengan elemen terakhir ( c) dalam set ( ["c"]), lalu tambahkan elemen terakhir kedua ( b) ke depan, akhir dan setiap posisi yang mungkin ada di tengah, membuatnya ["bc", "cb"]dan kemudian dengan cara yang sama akan menambah elemen berikutnya dari belakang ( a) ke setiap string di set membuatnya:
"a"+"bc"=["abc","bac","bca"] and "a"+"cb"=["acb","cab","cba"]
Demikian seluruh permutasi:
["abc","bac","bca","acb","cab","cba"]
Kode:
publicclassTest{staticSet<String> permutations;staticSet<String> result =newHashSet<String>();publicstaticSet<String> permutation(String string){
permutations =newHashSet<String>();int n = string.length();for(int i = n -1; i >=0; i--){
shuffle(string.charAt(i));}return permutations;}privatestaticvoid shuffle(char c){if(permutations.size()==0){
permutations.add(String.valueOf(c));}else{Iterator<String> it = permutations.iterator();for(int i =0; i < permutations.size(); i++){String temp1;for(; it.hasNext();){
temp1 = it.next();for(int k =0; k < temp1.length()+1; k +=1){StringBuilder sb =newStringBuilder(temp1);
sb.insert(k, c);
result.add(sb.toString());}}}
permutations = result;//'result' has to be refreshed so that in next run it doesn't contain stale values.
result =newHashSet<String>();}}publicstaticvoid main(String[] args){Set<String> result = permutation("abc");System.out.println("\nThere are total of "+ result.size()+" permutations:");Iterator<String> it = result.iterator();while(it.hasNext()){System.out.println(it.next());}}}
Ini mirip dengan solusi yang diberikan di sini: geeksforgeeks.org/… , yang melibatkan pengulangan dan kompleksitas waktu O (n * n!).
Nakul Kumar
5
implementasi python
def getPermutation(s, prefix=''):if len(s)==0:
print prefix
for i in range(len(s)):
getPermutation(s[0:i]+s[i+1:len(s)],prefix+s[i])
getPermutation('abcd','')
ketika input adalah string kosong, satu-satunya permutasi adalah string kosong. Coba untuk masing-masing huruf dalam string dengan menjadikannya sebagai huruf pertama dan kemudian temukan semua permutasi dari huruf yang tersisa menggunakan panggilan rekursif.
import java.util.ArrayList;import java.util.List;classPermutation{privatestaticList<String> permutation(String prefix,String str){List<String> permutations =newArrayList<>();int n = str.length();if(n ==0){
permutations.add(prefix);}else{for(int i =0; i < n; i++){
permutations.addAll(permutation(prefix + str.charAt(i), str.substring(i +1, n)+ str.substring(0, i)));}}return permutations;}publicstaticvoid main(String[] args){List<String> perms = permutation("","abcd");String[] array =newString[perms.size()];for(int i =0; i < perms.size(); i++){
array[i]= perms.get(i);}int x = array.length;for(finalString anArray : array){System.out.println(anArray);}}}
Konsep inti: Memecah daftar panjang menjadi daftar + rekursi yang lebih kecil
Jawaban panjang dengan daftar contoh [1, 2, 3, 4]:
Bahkan untuk daftar 4 sudah agak membingungkan mencoba untuk mendaftar semua permutasi yang mungkin ada di kepala Anda, dan apa yang perlu kita lakukan adalah persis untuk menghindari itu. Sangat mudah bagi kita untuk memahami bagaimana membuat semua permutasi daftar ukuran 0, 1, dan 2, jadi yang perlu kita lakukan adalah memecahnya ke salah satu ukuran tersebut dan menggabungkannya kembali dengan benar. Bayangkan mesin jackpot: algoritma ini akan mulai berputar dari kanan ke kiri, dan menulis
kembali kosong / daftar 1 ketika ukuran daftar adalah 0 atau 1
menangani ketika ukuran daftar adalah 2 (misalnya [3, 4]), dan menghasilkan 2 permutasi ([3, 4] & [4, 3])
Untuk setiap item, tandai sebagai yang terakhir di yang terakhir, dan temukan semua permutasi untuk sisa item dalam daftar. (mis. letakkan [4] di atas meja, dan lemparkan [1, 2, 3] ke permutasi lagi)
Sekarang dengan semua permutasi itu adalah anak-anak, letakkan dirinya kembali ke akhir daftar (mis: [1, 2, 3] [, 4], [1, 3, 2] [, 4], [2, 3, 1] [, 4], ...)
/** Returns an array list containing all
* permutations of the characters in s. */publicstaticArrayList<String> permute(String s){ArrayList<String> perms =newArrayList<>();int slen = s.length();if(slen >0){// Add the first character from s to the perms array list.
perms.add(Character.toString(s.charAt(0)));// Repeat for all additional characters in s.for(int i =1; i < slen;++i){// Get the next character from s.char c = s.charAt(i);// For each of the strings currently in perms do the following:int size = perms.size();for(int j =0; j < size;++j){// 1. remove the stringString p = perms.remove(0);int plen = p.length();// 2. Add plen + 1 new strings to perms. Each new string// consists of the removed string with the character c// inserted into it at a unique location.for(int k =0; k <= plen;++k){
perms.add(p.substring(0, k)+ c + p.substring(k));}}}}return perms;}
Inilah yang saya lakukan melalui pemahaman dasar tentang Permutasi dan pemanggilan fungsi Rekursif. Butuh sedikit waktu tetapi dilakukan secara mandiri.
Saya tidak menemukan jawaban ini berguna karena mengandung penjelasan dan menggunakan algoritma yang sama seperti beberapa jawaban lain yang melakukan memberikan penjelasan.
Bernhard Barker
1
//Rotate and create words beginning with all letter possible and push to stack 1//Read from stack1 and for each word create words with other letters at the next location by rotation and so on /* eg : man
1. push1 - man, anm, nma
2. pop1 - nma , push2 - nam,nma
pop1 - anm , push2 - amn,anm
pop1 - man , push2 - mna,man
*/publicclassStringPermute{staticString str;staticString word;staticint top1 =-1;staticint top2 =-1;staticString[] stringArray1;staticString[] stringArray2;staticint strlength =0;publicstaticvoid main(String[] args)throwsIOException{System.out.println("Enter String : ");InputStreamReader isr =newInputStreamReader(System.in);BufferedReader bfr =newBufferedReader(isr);
str = bfr.readLine();
word = str;
strlength = str.length();int n =1;for(int i =1; i <= strlength; i++){
n = n * i;}
stringArray1 =newString[n];
stringArray2 =newString[n];
push(word,1);
doPermute();
display();}publicstaticvoid push(String word,int x){if(x ==1)
stringArray1[++top1]= word;else
stringArray2[++top2]= word;}publicstaticString pop(int x){if(x ==1)return stringArray1[top1--];elsereturn stringArray2[top2--];}publicstaticvoid doPermute(){for(int j = strlength; j >=2; j--)
popper(j);}publicstaticvoid popper(int length){// pop from stack1 , rotate each word n times and push to stack 2if(top1 >-1){while(top1 >-1){
word = pop(1);for(int j =0; j < length; j++){
rotate(length);
push(word,2);}}}// pop from stack2 , rotate each word n times w.r.t position and push to// stack 1else{while(top2 >-1){
word = pop(2);for(int j =0; j < length; j++){
rotate(length);
push(word,1);}}}}publicstaticvoid rotate(int position){char[] charstring =newchar[100];for(int j =0; j < word.length(); j++)
charstring[j]= word.charAt(j);int startpos = strlength - position;char temp = charstring[startpos];for(int i = startpos; i < strlength -1; i++){
charstring[i]= charstring[i +1];}
charstring[strlength -1]= temp;
word =newString(charstring).trim();}publicstaticvoid display(){int top;if(top1 >-1){while(top1 >-1)System.out.println(stringArray1[top1--]);}else{while(top2 >-1)System.out.println(stringArray2[top2--]);}}}
Cara sederhana lainnya adalah dengan loop melalui string, pilih karakter yang belum digunakan dan letakkan di buffer, lanjutkan loop sampai ukuran buffer sama dengan panjang string. Saya lebih suka solusi pelacakan ini karena:
Mudah dimengerti
Mudah untuk menghindari duplikasi
Outputnya diurutkan
Berikut adalah kode java:
List<String> permute(String str){if(str ==null){returnnull;}char[] chars = str.toCharArray();boolean[] used =newboolean[chars.length];List<String> res =newArrayList<String>();StringBuilder sb =newStringBuilder();Arrays.sort(chars);
helper(chars, used, sb, res);return res;}void helper(char[] chars,boolean[] used,StringBuilder sb,List<String> res){if(sb.length()== chars.length){
res.add(sb.toString());return;}for(int i =0; i < chars.length; i++){// avoid duplicatesif(i >0&& chars[i]== chars[i -1]&&!used[i -1]){continue;}// pick the character that has not used yetif(!used[i]){
used[i]=true;
sb.append(chars[i]);
helper(chars, used, sb, res);// back tracking
sb.deleteCharAt(sb.length()-1);
used[i]=false;}}}
Rekursi tidak diperlukan, bahkan Anda dapat menghitung permutasi secara langsung , solusi ini menggunakan obat generik untuk mengubah urutan array apa pun.
Berikut adalah informasi yang bagus tentang algoritme ini.
Untuk pengembang C # di sini adalah implementasi yang lebih bermanfaat.
publicstaticvoid main(String[] args){String word ="12345";Character[] array =ArrayUtils.toObject(word.toCharArray());long[] factorials =Permutation.getFactorials(array.length +1);for(long i =0; i < factorials[array.length]; i++){Character[] permutation =Permutation.<Character>getPermutation(i, array, factorials);
printPermutation(permutation);}}privatestaticvoid printPermutation(Character[] permutation){for(int i =0; i < permutation.length; i++){System.out.print(permutation[i]);}System.out.println();}
Algoritma ini memiliki kompleksitas ruang dan waktu O (N) untuk menghitung setiap permutasi .
Implementasi java untuk mencetak semua permutasi dari string yang diberikan mempertimbangkan karakter duplikat dan hanya mencetak karakter unik adalah sebagai berikut:
Ini dapat dilakukan secara iteratif dengan hanya memasukkan setiap huruf dari string pada gilirannya di semua lokasi dari hasil parsial sebelumnya.
Kita mulai dengan [A], yang dengan Bmenjadi [BA, AB], dan dengan C, [CBA, BCA, BAC, CAB, etc].
Waktu berjalan akan menjadi O(n!), yang, untuk kasus uji ABCD, adalah 1 x 2 x 3 x 4.
Dalam produk di atas, 1untuk A, 2untuk B, dll.
Sampel dart:
void main(){String insertAt(String a,String b,int index){return a.substring(0, index)+ b + a.substring(index);}List<String>Permute(String word){
var letters = word.split('');
var p_list =[ letters.first ];for(var c in letters.sublist(1)){
var new_list =[];for(var p in p_list)for(int i =0; i <= p.length; i++)
new_list.add(insertAt(p, c, i));
p_list = new_list;}return p_list;}
print(Permute("ABCD"));}
Jawaban:
(melalui Pengantar Pemrograman di Jawa )
sumber
n==0
, Anda dapat menghentikan level sebelumnya padan==1
dan mencetakprefix + str
.Gunakan rekursi.
sumber
Inilah solusi saya yang didasarkan pada gagasan buku "Cracking the Coding Wawancara" (P54):
Menjalankan output dari string "abcd":
Langkah 1: Gabungkan [a] dan b: [ba, ab]
Langkah 2: Gabungkan [ba, ab] dan c: [cba, bca, bac, cab, acb, abc]
Langkah 3: Gabungkan [cba, bca, bac, cab, acb, abc] dan d: [dcba, cdba, cbda, cbad, dbca, bdca, bcda, bcad, dbac, bdac, badc, bacd, dcab, cdab, cadb , cabd, dacb, adcb, acdb, acbd, dabc, adbc, abdc, abcd]
sumber
Dari semua solusi yang diberikan di sini dan di forum lain, saya paling suka Mark Byers. Deskripsi itu sebenarnya membuat saya berpikir dan mengkodekannya sendiri. Sayang sekali saya tidak bisa memilih solusinya karena saya pemula.
Bagaimanapun di sini adalah implementasi dari deskripsinya
Saya lebih suka solusi ini daripada yang pertama di utas ini karena solusi ini menggunakan StringBuffer. Saya tidak akan mengatakan solusi saya tidak membuat string sementara (itu sebenarnya tidak di
system.out.println
manatoString()
StringBuffer dipanggil). Tapi saya hanya merasa ini lebih baik daripada solusi pertama di mana terlalu banyak string literal dibuat. Mungkin ada orang kinerja di luar sana yang dapat mengevaluasi ini dalam hal 'memori' (untuk 'waktu' itu sudah terlambat karena 'swap' tambahan)sumber
if(index == str.length())
dandoPerm(str, index + 1);
? ThecurrPos
tampaknya tidak perlu di sini.Solusi yang sangat mendasar di Jawa adalah dengan menggunakan rekursi + Set (untuk menghindari pengulangan) jika Anda ingin menyimpan dan mengembalikan string solusi:
sumber
Semua kontributor sebelumnya telah melakukan pekerjaan yang hebat menjelaskan dan menyediakan kode. Saya pikir saya harus membagikan pendekatan ini juga karena mungkin membantu seseorang juga. Solusinya didasarkan pada ( algoritma heaps ' )
Beberapa barang:
Perhatikan item terakhir yang digambarkan dalam excel hanya untuk membantu Anda memvisualisasikan logika dengan lebih baik. Jadi, nilai aktual pada kolom terakhir adalah 2,1,0 (jika kita menjalankan kode karena kita berurusan dengan array dan array mulai dengan 0).
Algoritma swapping terjadi berdasarkan nilai genap atau ganjil dari posisi saat ini. Ini sangat jelas jika Anda melihat di mana metode swap dipanggil. Anda dapat melihat apa yang terjadi.
Inilah yang terjadi:
sumber
Yang ini tanpa rekursi
sumber
System.out.println(permute("AABBC").size());
menampilkan 45, tetapi sebenarnya 5! = 120Mari kita gunakan input
abc
sebagai contoh.Mulailah hanya dengan elemen terakhir (
c
) dalam set (["c"]
), lalu tambahkan elemen terakhir kedua (b
) ke depan, akhir dan setiap posisi yang mungkin ada di tengah, membuatnya["bc", "cb"]
dan kemudian dengan cara yang sama akan menambah elemen berikutnya dari belakang (a
) ke setiap string di set membuatnya:Demikian seluruh permutasi:
Kode:
sumber
Nah, inilah solusi yang elegan, non-rekursif, O (n!):
sumber
Salah satu solusi sederhana bisa saja tetap bertukar karakter secara rekursif menggunakan dua petunjuk.
sumber
implementasi python
sumber
ini bekerja untuk saya ..
sumber
Gunakan rekursi.
ketika input adalah string kosong, satu-satunya permutasi adalah string kosong. Coba untuk masing-masing huruf dalam string dengan menjadikannya sebagai huruf pertama dan kemudian temukan semua permutasi dari huruf yang tersisa menggunakan panggilan rekursif.
sumber
Biarkan saya mencoba untuk mengatasi masalah ini dengan Kotlin:
Konsep inti: Memecah daftar panjang menjadi daftar + rekursi yang lebih kecil
Jawaban panjang dengan daftar contoh [1, 2, 3, 4]:
Bahkan untuk daftar 4 sudah agak membingungkan mencoba untuk mendaftar semua permutasi yang mungkin ada di kepala Anda, dan apa yang perlu kita lakukan adalah persis untuk menghindari itu. Sangat mudah bagi kita untuk memahami bagaimana membuat semua permutasi daftar ukuran 0, 1, dan 2, jadi yang perlu kita lakukan adalah memecahnya ke salah satu ukuran tersebut dan menggabungkannya kembali dengan benar. Bayangkan mesin jackpot: algoritma ini akan mulai berputar dari kanan ke kiri, dan menulis
sumber
sumber
sumber
Berikut ini adalah solusi rekursif minimalis langsung di Jawa:
sumber
Kita dapat menggunakan faktorial untuk menemukan berapa banyak string yang dimulai dengan huruf tertentu.
Contoh: ambil input
abcd
.(3!) == 6
string akan dimulai dengan setiap hurufabcd
.sumber
Inilah yang saya lakukan melalui pemahaman dasar tentang Permutasi dan pemanggilan fungsi Rekursif. Butuh sedikit waktu tetapi dilakukan secara mandiri.
yang menghasilkan Output sebagai
[abc, acb, bac, bca, cab, cba]
.Logika dasar di baliknya adalah
Untuk setiap karakter, anggap sebagai karakter pertama & temukan kombinasi karakter yang tersisa. mis
[abc](Combination of abc)->
.a->[bc](a x Combination of (bc))->{abc,acb}
b->[ac](b x Combination of (ac))->{bac,bca}
c->[ab](c x Combination of (ab))->{cab,cba}
Dan kemudian secara rekursif memanggil masing-masing
[bc]
,[ac]
&[ab]
secara mandiri.sumber
Implementasi Java tanpa rekursi
sumber
// masukkan setiap karakter ke dalam daftar array
sumber
sumber
Cara sederhana lainnya adalah dengan loop melalui string, pilih karakter yang belum digunakan dan letakkan di buffer, lanjutkan loop sampai ukuran buffer sama dengan panjang string. Saya lebih suka solusi pelacakan ini karena:
Berikut adalah kode java:
Input str: 1231
Daftar keluaran: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}
Memperhatikan bahwa output diurutkan, dan tidak ada hasil duplikat.
sumber
Rekursi tidak diperlukan, bahkan Anda dapat menghitung permutasi secara langsung , solusi ini menggunakan obat generik untuk mengubah urutan array apa pun.
Berikut adalah informasi yang bagus tentang algoritme ini.
Untuk pengembang C # di sini adalah implementasi yang lebih bermanfaat.
Algoritma ini memiliki kompleksitas ruang dan waktu O (N) untuk menghitung setiap permutasi .
sumber
Permutasi String:
sumber
Berikut adalah metode lain yang lebih sederhana untuk melakukan Permutasi string.
sumber
Implementasi java untuk mencetak semua permutasi dari string yang diberikan mempertimbangkan karakter duplikat dan hanya mencetak karakter unik adalah sebagai berikut:
sumber
sumber
Ini dapat dilakukan secara iteratif dengan hanya memasukkan setiap huruf dari string pada gilirannya di semua lokasi dari hasil parsial sebelumnya.
Kita mulai dengan
[A]
, yang denganB
menjadi[BA, AB]
, dan denganC
,[CBA, BCA, BAC, CAB, etc]
.Waktu berjalan akan menjadi
O(n!)
, yang, untuk kasus ujiABCD
, adalah1 x 2 x 3 x 4
.Dalam produk di atas,
1
untukA
,2
untukB
, dll.Sampel dart:
sumber
Berikut ini adalah implementasi java:
http://ideone.com/nWPb3k
sumber