Gerando todas as permutações de uma determinada string
418
Qual é uma maneira elegante de encontrar todas as permutações de uma string? Por exemplo, permutação para ba, seria bae ab, mas e quanto a string mais longa, como abcdefgh? Existe algum exemplo de implementação Java?
Há uma suposição que precisa ser mencionada. Os personagens são únicos. Por exemplo, para uma String "aaaa", há apenas uma resposta. Para se ter uma resposta mais geral, você pode salvar as cordas em um conjunto para evitará a duplicação
Afshin Moazami
1
A repetição de caracteres é permitida ou a repetição de caracteres não é permitida? Uma única sequência de caracteres pode ter várias ocorrências do mesmo caractere?
Anderson Green
2
Leia a teoria (ou se, como eu, você é preguiçoso, vá para en.wikipedia.org/wiki/Permutation ) e implemente um algoritmo real. Basicamente, você pode gerar uma sequência de ordenações de elementos (o fato de que é uma cadeia de caracteres é irrelevante) e percorrer as ordenações até voltar ao início. Evite qualquer coisa que envolva recursão ou manipulação de cordas.
CurtainDog
Respostas:
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));}}
Isso não é ciência de foguetes, vim com a mesma resposta. Pequenos ajustes: em vez de repetir até n==0, você pode parar um nível mais cedo n==1e imprimir prefix + str.
lambshaanxy
7
"qual é a complexidade de tempo e espaço disso?" sem algum tipo de resposta parcial em cache, qualquer algoritmo que produz permutação é o (n!) porque o resultado definido para a pergunta de permutação é fatorial para a entrada.
precisa saber é o seguinte
9
Elegante sim. Mas uma solução que se converte em uma matriz de caracteres e troque para gerar as permutações exigirá muito menos cópia e gerará muito menos lixo. Além disso, esse algoritmo falha ao considerar caracteres repetidos.
Gene
20
@AfshinMoazami Acho que str.substring (i + 1, n) pode ser substituído por str.substring (i + 1). O uso de str.substring (i) causará o java.lang.StackOverflowError.
precisa saber é o seguinte
196
Use recursão.
Tente cada uma das letras como a primeira letra e encontre todas as permutações das letras restantes usando uma chamada recursiva.
O caso base é quando a entrada é uma sequência vazia, a única permutação é a sequência vazia.
Como você pode adicionar um tipo de retorno ao método permute? O compilador não pode determinar o tipo de retorno desse método a cada iteração, mesmo que seja obviamente um tipo String.
user1712095
Como você garante permutações distintas nesse método?
kapad
70
Aqui está minha solução, baseada na idéia do livro "Quebrando a entrevista de codificação" (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;}
Página (71) em Cracking the Coding Interview Book, 6ª Edição. :)
KarimIhab
5
Esta é realmente uma boa solução? Ele se baseia em armazenar os resultados em uma lista, portanto, para uma string de entrada curta, ela fica fora de controle.
Androrider
o que a mesclagem faz?
Basavaraj Walikar 15/02/19
Ele insere c em todas as posições possíveis de cada string na lista, portanto, se a lista contiver apenas ["b"] e c for "a", o resultado da mesclagem será ["ab", "ba"] aqui a mesma solução com o Swift gist.github. com / daniaDlbani / 3bc10e02541f9ba310d546040c5322fc
Dania Delbani
53
De todas as soluções dadas aqui e em outros fóruns, gostei mais de Mark Byers. Essa descrição realmente me fez pensar e codificá-la. Pena que não posso votar em sua solução, pois sou novato.
Enfim, aqui está a minha implementação de sua descrição
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);}}
Prefiro esta solução à frente da primeira neste segmento, porque esta solução usa StringBuffer. Eu não diria que minha solução não cria nenhuma string temporária (na verdade, é system.out.printlnonde o toString()StringBuffer é chamado). Mas acho que isso é melhor do que a primeira solução em que muitos literais de string são criados. Pode ser um cara de desempenho por aí que pode avaliar isso em termos de 'memória' (por 'tempo' já está atrasado devido a essa 'troca' extra)
Por que não apenas fazer if(index == str.length())e doPerm(str, index + 1);? O currPosparece desnecessário aqui.
Robur_131
Desculpe, você pode elaborar mais sobre a questão? Você está apenas sugerindo a não usar currPos variáveis extras (usado por causa de várias ocorrências e também de legibilidade) se não cole a solução que você está sugerindo para dar uma olhada
yaradla srikanth
Ah, entendi que você quis dizer a alteração na condição básica com indexação direta. Funciona bem. Só que a solução que apresentei foi influenciada principalmente pelas outras soluções que frequentemente passavam pela cadeia truncada em vez da original (caso 0 faz sentido). No entanto, obrigado por apontar. Vou ver se consigo editar, já faz anos desde que entrei neste site.
srikanth yaradla 17/08/19
22
Uma solução muito básica em Java é usar recursão + Set (para evitar repetições) se você deseja armazenar e retornar as strings da solução:
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!), uma vez que temos n! permutações em uma determinada seqüência de comprimento n.
Zok 27/02
17
Todos os colaboradores anteriores fizeram um ótimo trabalho explicando e fornecendo o código. Eu pensei que deveria compartilhar essa abordagem também, porque pode ajudar alguém também. A solução é baseada no algoritmo ( heaps ' )
Algumas coisas:
Observe que o último item descrito no Excel é apenas para ajudá-lo a visualizar melhor a lógica. Portanto, os valores reais na última coluna seriam 2,1,0 (se executássemos o código porque estamos lidando com matrizes e matrizes começam com 0).
O algoritmo de troca acontece com base em valores pares ou ímpares da posição atual. É muito auto-explicativo se você olhar para onde o método de troca está sendo chamado. Você pode ver o que está acontecendo.
Aqui está o que acontece:
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;}
esta solução parece estar errada System.out.println(permute("AABBC").size());exibe 45, mas na verdade 5! = 120
Mladen Adamovic
11
Vamos usar a entrada abccomo um exemplo.
Comece com apenas o último elemento ( c) em um conjunto ( ["c"]) e adicione o segundo último elemento ( b) à frente, extremidade e todas as posições possíveis no meio, criando-o ["bc", "cb"]e, da mesma maneira, adicionará o próximo elemento do back ( a) para cada string do conjunto, tornando-o:
"a"+"bc"=["abc","bac","bca"] and "a"+"cb"=["acb","cab","cba"]
Assim permutação inteira:
["abc","bac","bca","acb","cab","cba"]
Código:
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());}}}
Isso é semelhante à solução fornecida aqui: geeksforgeeks.org/… , envolvendo retorno e complexidade de tempo O (n * n!).
Nakul Kumar 5/02
5
implementação de 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','')
quando a entrada é uma sequência vazia, a única permutação é uma sequência vazia.Tente cada uma das letras da sequência, tornando-a como primeira letra e, em seguida, encontre todas as permutações das demais letras usando uma chamada recursiva.
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);}}}
Conceito básico: divida a lista longa em lista menor + recursão
Resposta longa com lista de exemplos [1, 2, 3, 4]:
Mesmo para uma lista de quatro, já é meio confuso tentar listar todas as permutações possíveis em sua cabeça, e o que precisamos fazer é exatamente para evitar isso. É fácil para nós entender como fazer todas as permutações da lista de tamanhos 0, 1 e 2; portanto, tudo o que precisamos fazer é dividi-las em qualquer um desses tamanhos e combiná-las corretamente. Imagine uma máquina de jackpot: esse algoritmo começará a girar da direita para a esquerda e anote
retornar vazio / lista de 1 quando o tamanho da lista for 0 ou 1
manipular quando o tamanho da lista for 2 (por exemplo, [3, 4]) e gerar as 2 permutações ([3, 4] e [4, 3])
Para cada item, marque-o como o último no último e encontre todas as permutações para o restante do item na lista. (por exemplo, coloque [4] na mesa e jogue [1, 2, 3] em permutação novamente)
Agora, com toda permutação de crianças, volte ao final da lista (por exemplo: [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;}
Foi o que fiz através do entendimento básico de Permutações e chamadas de funções recursivas. Demora um pouco de tempo, mas é feito de forma independente.
que gera saída como [abc, acb, bac, bca, cab, cba].
A lógica básica por trás disso é
Para cada personagem, considere-o como primeiro personagem e encontre as combinações dos personagens restantes. por exemplo [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}
E então recursivamente chamando cada um [bc], [ac]e [ab]independentemente.
Eu não encontrar esta resposta útil, pois não contém qualquer explicação e usa o mesmo algoritmo que algumas outras respostas que fazer fornecer uma explicação.
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--]);}}}
Outra maneira simples é fazer um loop pela string, escolher o caractere que ainda não foi usado e colocá-lo em um buffer, continuar o loop até que o tamanho do buffer seja igual ao comprimento da string. Eu gosto mais dessa solução de rastreamento de volta porque:
Fácil de entender
Fácil de evitar duplicação
A saída é classificada
Aqui está o código 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;}}}
Entrada str: 1231
Lista de saída: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}
Observe que a saída está classificada e não há resultado duplicado.
Uma implementação java para imprimir todas as permutações de uma determinada string, considerando caracteres duplicados e imprimindo apenas caracteres únicos, é a seguinte:
Isso pode ser feito iterativamente, simplesmente inserindo cada letra da string em todos os locais dos resultados parciais anteriores.
Começamos com [A], que com Btorna - se [BA, AB]e com C,[CBA, BCA, BAC, CAB, etc] .
O tempo de execução seria O(n!), que, para o caso de teste ABCD, é 1 x 2 x 3 x 4.
No produto acima, o 1é para A, o 2é para Betc.
Amostra de dardo:
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"));}
Respostas:
(via Introdução à programação em Java )
fonte
n==0
, você pode parar um nível mais cedon==1
e imprimirprefix + str
.Use recursão.
fonte
Aqui está minha solução, baseada na idéia do livro "Quebrando a entrevista de codificação" (P54):
Execução da saída da sequência "abcd":
Etapa 1: mesclar [a] eb: [ba, ab]
Etapa 2: Mesclar [ba, ab] e c: [cba, bca, bac, cab, acb, abc]
Etapa 3: Mesclar [cba, bca, bac, cab, acb, abc] e 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]
fonte
De todas as soluções dadas aqui e em outros fóruns, gostei mais de Mark Byers. Essa descrição realmente me fez pensar e codificá-la. Pena que não posso votar em sua solução, pois sou novato.
Enfim, aqui está a minha implementação de sua descrição
Prefiro esta solução à frente da primeira neste segmento, porque esta solução usa StringBuffer. Eu não diria que minha solução não cria nenhuma string temporária (na verdade, é
system.out.println
onde otoString()
StringBuffer é chamado). Mas acho que isso é melhor do que a primeira solução em que muitos literais de string são criados. Pode ser um cara de desempenho por aí que pode avaliar isso em termos de 'memória' (por 'tempo' já está atrasado devido a essa 'troca' extra)fonte
if(index == str.length())
edoPerm(str, index + 1);
? OcurrPos
parece desnecessário aqui.Uma solução muito básica em Java é usar recursão + Set (para evitar repetições) se você deseja armazenar e retornar as strings da solução:
fonte
Todos os colaboradores anteriores fizeram um ótimo trabalho explicando e fornecendo o código. Eu pensei que deveria compartilhar essa abordagem também, porque pode ajudar alguém também. A solução é baseada no algoritmo ( heaps ' )
Algumas coisas:
Observe que o último item descrito no Excel é apenas para ajudá-lo a visualizar melhor a lógica. Portanto, os valores reais na última coluna seriam 2,1,0 (se executássemos o código porque estamos lidando com matrizes e matrizes começam com 0).
O algoritmo de troca acontece com base em valores pares ou ímpares da posição atual. É muito auto-explicativo se você olhar para onde o método de troca está sendo chamado. Você pode ver o que está acontecendo.
Aqui está o que acontece:
fonte
Este é sem recursão
fonte
System.out.println(permute("AABBC").size());
exibe 45, mas na verdade 5! = 120Vamos usar a entrada
abc
como um exemplo.Comece com apenas o último elemento (
c
) em um conjunto (["c"]
) e adicione o segundo último elemento (b
) à frente, extremidade e todas as posições possíveis no meio, criando-o["bc", "cb"]
e, da mesma maneira, adicionará o próximo elemento do back (a
) para cada string do conjunto, tornando-o:Assim permutação inteira:
Código:
fonte
Bem, aqui está uma solução O (n!) Elegante e não recursiva:
fonte
Uma das soluções simples poderia ser apenas trocar os caracteres recursivamente usando dois ponteiros.
fonte
implementação de python
fonte
isso funcionou para mim ..
fonte
Use recursão.
quando a entrada é uma sequência vazia, a única permutação é uma sequência vazia.Tente cada uma das letras da sequência, tornando-a como primeira letra e, em seguida, encontre todas as permutações das demais letras usando uma chamada recursiva.
fonte
Deixe-me tentar resolver esse problema com o Kotlin:
Conceito básico: divida a lista longa em lista menor + recursão
Resposta longa com lista de exemplos [1, 2, 3, 4]:
Mesmo para uma lista de quatro, já é meio confuso tentar listar todas as permutações possíveis em sua cabeça, e o que precisamos fazer é exatamente para evitar isso. É fácil para nós entender como fazer todas as permutações da lista de tamanhos 0, 1 e 2; portanto, tudo o que precisamos fazer é dividi-las em qualquer um desses tamanhos e combiná-las corretamente. Imagine uma máquina de jackpot: esse algoritmo começará a girar da direita para a esquerda e anote
fonte
fonte
fonte
Aqui está uma solução recursiva minimalista e direta em Java:
fonte
Podemos usar fatorial para descobrir quantas seqüências iniciadas com uma letra específica.
Exemplo: pegue a entrada
abcd
.(3!) == 6
strings começarão com cada letra deabcd
.fonte
Foi o que fiz através do entendimento básico de Permutações e chamadas de funções recursivas. Demora um pouco de tempo, mas é feito de forma independente.
que gera saída como
[abc, acb, bac, bca, cab, cba]
.A lógica básica por trás disso é
Para cada personagem, considere-o como primeiro personagem e encontre as combinações dos personagens restantes. por exemplo
[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}
E então recursivamente chamando cada um
[bc]
,[ac]
e[ab]
independentemente.fonte
Implementação Java sem recursão
fonte
// insere cada caractere em um arraylist
fonte
fonte
Outra maneira simples é fazer um loop pela string, escolher o caractere que ainda não foi usado e colocá-lo em um buffer, continuar o loop até que o tamanho do buffer seja igual ao comprimento da string. Eu gosto mais dessa solução de rastreamento de volta porque:
Aqui está o código java:
Entrada str: 1231
Lista de saída: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}
Observe que a saída está classificada e não há resultado duplicado.
fonte
A recursão não é necessária; mesmo que você possa calcular diretamente qualquer permutação , esta solução usa genéricos para permutar qualquer matriz.
Aqui está uma boa informação sobre este algoritmo.
Para desenvolvedores de C #, aqui está uma implementação mais útil.
Este algoritmo possui complexidade de tempo e espaço O (N) para calcular cada permutação .
fonte
Permutação de String:
fonte
Aqui está outro método mais simples de fazer a permutação de uma string.
fonte
Uma implementação java para imprimir todas as permutações de uma determinada string, considerando caracteres duplicados e imprimindo apenas caracteres únicos, é a seguinte:
fonte
fonte
Isso pode ser feito iterativamente, simplesmente inserindo cada letra da string em todos os locais dos resultados parciais anteriores.
Começamos com
[A]
, que comB
torna - se[BA, AB]
e comC
,[CBA, BCA, BAC, CAB, etc]
.O tempo de execução seria
O(n!)
, que, para o caso de testeABCD
, é1 x 2 x 3 x 4
.No produto acima, o
1
é paraA
, o2
é paraB
etc.Amostra de dardo:
fonte
Aqui está uma implementação java:
http://ideone.com/nWPb3k
fonte