recursivo permutar permutaciones permutacion mostrar escribir con combinaciones array agrupaciones java algorithm

java - permutar - permutaciones recursivo



Generando todas las permutaciones de una cadena dada (30)

¿Qué es una manera elegante de encontrar todas las permutaciones de una cadena. Por ejemplo, ba , sería ba y ab , pero ¿qué pasa con abcdefgh ? ¿Hay algún ejemplo de implementación de Java?


// inserta cada personaje en un arraylist

static ArrayList al = new ArrayList(); private static void findPermutation (String str){ for (int k = 0; k < str.length(); k++) { addOneChar(str.charAt(k)); } } //insert one char into ArrayList private static void addOneChar(char ch){ String lastPerStr; String tempStr; ArrayList locAl = new ArrayList(); for (int i = 0; i < al.size(); i ++ ){ lastPerStr = al.get(i).toString(); //System.out.println("lastPerStr: " + lastPerStr); for (int j = 0; j <= lastPerStr.length(); j++) { tempStr = lastPerStr.substring(0,j) + ch + lastPerStr.substring(j, lastPerStr.length()); locAl.add(tempStr); //System.out.println("tempStr: " + tempStr); } } if(al.isEmpty()){ al.add(ch); } else { al.clear(); al = locAl; } } private static void printArrayList(ArrayList al){ for (int i = 0; i < al.size(); i++) { System.out.print(al.get(i) + " "); } }


A continuación se muestra una implementación en java para imprimir todas las permutaciones de una cadena dada considerando caracteres duplicados e imprime solo caracteres únicos:

import java.util.Set; import java.util.HashSet; public class PrintAllPermutations2 { public static void main(String[] args) { String str = "AAC"; PrintAllPermutations2 permutation = new PrintAllPermutations2(); Set<String> uniqueStrings = new HashSet<>(); permutation.permute("", str, uniqueStrings); } void permute(String prefixString, String s, Set<String> set) { int n = s.length(); if(n == 0) { if(!set.contains(prefixString)) { System.out.println(prefixString); set.add(prefixString); } } else { for(int i=0; i<n; i++) { permute(prefixString + s.charAt(i), s.substring(0,i) + s.substring(i+1,n), set); } } } }


Aquí está mi solución que se basa en la idea del libro "Cracking the Coding Interview" (P54):

/** * List permutations of a string. * * @param s the input string * @return the list of permutations */ public static ArrayList<String> permutation(String s) { // The result ArrayList<String> res = new ArrayList<String>(); // If input string''s length is 1, return {s} if (s.length() == 1) { res.add(s); } else if (s.length() > 1) { int lastIndex = s.length() - 1; // Find out the last character String last = s.substring(lastIndex); // Rest of the string String 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" ... } */ public static ArrayList<String> merge(ArrayList<String> list, String c) { ArrayList<String> res = new ArrayList<>(); // Loop through all the string in the list for (String s : list) { // For each string, insert the last character to all possible positions // and add them to the new list for (int i = 0; i <= s.length(); ++i) { String ps = new StringBuffer(s).insert(i, c).toString(); res.add(ps); } } return res; }

Ejecución de la salida de la cadena "abcd":

  • Paso 1: Combinar [a] y b: [ba, ab]

  • Paso 2: Combinar [ba, ab] yc: [cba, bca, bac, cab, acb, abc]

  • Paso 3: Combinar [cba, bca, bac, cab, acb, abc] y 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]


Aquí hay dos versiones de c # (solo para referencia): 1. Imprime todas las permeaciones 2. devuelve todas las permutaciones

El compendio básico del algoritmo es (probablemente debajo del código es más intuitivo; sin embargo, aquí hay una explicación de lo que hace el código siguiente): - desde el índice actual hasta el resto de la colección, intercambie el elemento al índice actual - obtenga las permutaciones para los elementos restantes del siguiente índice de forma recursiva - restaure el orden, re-intercambiando

Nota: la función recursiva anterior se invocará desde el índice de inicio.

private void PrintAllPermutations(int[] a, int index, ref int count) { if (index == (a.Length - 1)) { count++; var s = string.Format("{0}: {1}", count, string.Join(",", a)); Debug.WriteLine(s); } for (int i = index; i < a.Length; i++) { Utilities.swap(ref a[i], ref a[index]); this.PrintAllPermutations(a, index + 1, ref count); Utilities.swap(ref a[i], ref a[index]); } } private int PrintAllPermutations(int[] a) { a.ThrowIfNull("a"); int count = 0; this.PrintAllPermutations(a, index:0, count: ref count); return count; }

versión 2 (igual que la anterior, pero devuelve las permutaciones en lugar de imprimir)

private int[][] GetAllPermutations(int[] a, int index) { List<int[]> permutations = new List<int[]>(); if (index == (a.Length - 1)) { permutations.Add(a.ToArray()); } for (int i = index; i < a.Length; i++) { Utilities.swap(ref a[i], ref a[index]); var r = this.GetAllPermutations(a, index + 1); permutations.AddRange(r); Utilities.swap(ref a[i], ref a[index]); } return permutations.ToArray(); } private int[][] GetAllPermutations(int[] p) { p.ThrowIfNull("p"); return this.GetAllPermutations(p, 0); }

Pruebas unitarias

[TestMethod] public void PermutationsTests() { List<int> input = new List<int>(); int[] output = { 0, 1, 2, 6, 24, 120 }; for (int i = 0; i <= 5; i++) { if (i != 0) { input.Add(i); } Debug.WriteLine("================PrintAllPermutations==================="); int count = this.PrintAllPermutations(input.ToArray()); Assert.IsTrue(count == output[i]); Debug.WriteLine("=====================GetAllPermutations================="); var r = this.GetAllPermutations(input.ToArray()); Assert.IsTrue(count == r.Length); for (int j = 1; j <= r.Length;j++ ) { string s = string.Format("{0}: {1}", j, string.Join(",", r[j - 1])); Debug.WriteLine(s); } Debug.WriteLine("No.OfElements: {0}, TotalPerms: {1}", i, count); } }


Aquí hay una implementación en java:

/* All Permutations of a String */ import java.util.*; import java.lang.*; import java.io.*; /* Complexity O(n*n!) */ class Ideone { public static ArrayList<String> strPerm(String str, ArrayList<String> list) { int len = str.length(); if(len==1){ list.add(str); return list; } list = strPerm(str.substring(0,len-1),list); int ls = list.size(); char ap = str.charAt(len-1); for(int i=0;i<ls;i++){ String temp = list.get(i); int tl = temp.length(); for(int j=0;j<=tl;j++){ list.add(temp.substring(0,j)+ap+temp.substring(j,tl)); } } while(true){ String temp = list.get(0); if(temp.length()<len) list.remove(temp); else break; } return list; } public static void main (String[] args) throws java.lang.Exception { String str = "abc"; ArrayList<String> list = new ArrayList<>(); list = strPerm(str,list); System.out.println("Total Permutations : "+list.size()); for(int i=0;i<list.size();i++) System.out.println(list.get(i)); } }

http://ideone.com/nWPb3k


Aquí hay una solución recursiva minimalista y sencilla en Java:

public static ArrayList<String> permutations(String s) { ArrayList<String> out = new ArrayList<String>(); if (s.length() == 1) { out.add(s); return out; } char first = s.charAt(0); String rest = s.substring(1); for (String permutation : permutations(rest)) { out.addAll(insertAtAllPositions(first, permutation)); } return out; } public static ArrayList<String> insertAtAllPositions(char ch, String s) { ArrayList<String> out = new ArrayList<String>(); for (int i = 0; i <= s.length(); ++i) { String inserted = s.substring(0, i) + ch + s.substring(i); out.add(inserted); } return out; }


Bueno, aquí hay una solución elegante, no recursiva, O (n!):

public static StringBuilder[] permutations(String s) { if (s.length() == 0) return null; int length = fact(s.length()); StringBuilder[] sb = new StringBuilder[length]; for (int i = 0; i < length; i++) { sb[i] = new StringBuilder(); } for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); int times = length / (i + 1); for (int j = 0; j < times; j++) { for (int k = 0; k < length / times; k++) { sb[j * length / times + k].insert(k, ch); } } } return sb; }


De todas las soluciones dadas aquí y en otros foros, me gustó más Mark Byers. Esa descripción en realidad me hizo pensar y codificarla yo mismo. Lástima que no puedo votar su solución ya que soy un novato.
De todos modos aquí está mi implementación de su descripción.

public class PermTest { public static void main(String[] args) throws Exception { String str = "abcdef"; StringBuffer strBuf = new StringBuffer(str); doPerm(strBuf,str.length()); } private static void doPerm(StringBuffer str, int index){ if(index <= 0) System.out.println(str); else { //recursively solve this by placing all other chars at current first pos doPerm(str, index-1); int currPos = str.length()-index; for (int i = currPos+1; i < str.length(); i++) {//start swapping all other chars with current first char swap(str,currPos, i); doPerm(str, index-1); swap(str,i, currPos);//restore back my string buffer } } } private static void swap(StringBuffer str, int pos1, int pos2){ char t1 = str.charAt(pos1); str.setCharAt(pos1, str.charAt(pos2)); str.setCharAt(pos2, t1); } }

Prefiero esta solución antes que la primera en este hilo porque esta solución usa StringBuffer. No diría que mi solución no crea una cadena temporal (en realidad lo hace en system.out.println donde se system.out.println toString() de StringBuffer). Pero siento que esto es mejor que la primera solución donde se crean demasiados literales de cadena. Puede ser que alguien de rendimiento pueda evaluar esto en términos de "memoria" (por "tiempo" ya se retrasa debido a ese "intercambio" adicional)


Este es sin recursión.

public static void permute(String s) { if(null==s || s.isEmpty()) { return; } // List containing words formed in each iteration List<String> strings = new LinkedList<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 list List<String> tempList = new LinkedList<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) */ private static Set<String> merge(Character c, String s) { if(s==null || s.isEmpty()) { return null; } int len = s.length(); StringBuilder sb = new StringBuilder(); Set<String> list = new HashSet<String>(); for(int i=0; i<= len; i++) { sb = new StringBuilder(); sb.append(s.substring(0, i) + c + s.substring(i, len)); list.add(sb.toString()); } return list; }


Esto es lo que hice a través de la comprensión básica de las permutaciones y la función recursiva de llamadas. Toma un poco de tiempo pero se hace de forma independiente.

public class LexicographicPermutations { public static void main(String[] args) { // TODO Auto-generated method stub String s="abc"; List<String>combinations=new ArrayList<String>(); combinations=permutations(s); Collections.sort(combinations); System.out.println(combinations); } private static List<String> permutations(String s) { // TODO Auto-generated method stub List<String>combinations=new ArrayList<String>(); if(s.length()==1){ combinations.add(s); } else{ for(int i=0;i<s.length();i++){ List<String>temp=permutations(s.substring(0, i)+s.substring(i+1)); for (String string : temp) { combinations.add(s.charAt(i)+string); } } } return combinations; }}

que genera la salida como [abc, acb, bac, bca, cab, cba] .

La lógica básica detrás de esto es

Para cada personaje, considérelo como primer personaje y encuentre las combinaciones de los caracteres restantes. por ejemplo, [abc](Combination of abc)-> .

  1. a->[bc](ax Combination of (bc))->{abc,acb}
  2. b->[ac](bx Combination of (ac))->{bac,bca}
  3. c->[ab](cx Combination of (ab))->{cab,cba}

Y luego recursivamente llamando a cada [bc] , [ac] y [ab] independiente.


Esto se puede hacer de forma iterativa simplemente insertando cada letra de la cadena en todas las ubicaciones de los resultados parciales anteriores.

Comenzamos con [A] , que con B convierte en [BA, AB] , y con C , [CBA, BCA, BAC, CAB, etc] .

El tiempo de ejecución sería O(n!) , Que, para el caso de prueba ABCD , es 1 x 2 x 3 x 4 .

En el producto anterior, el 1 es para A , el 2 es para B , etc.

Muestra 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")); }


Implementación de Java sin recursión.

public Set<String> permutate(String s){ Queue<String> permutations = new LinkedList<String>(); Set<String> v = new HashSet<String>(); permutations.add(s); while(permutations.size()!=0){ String str = permutations.poll(); if(!v.contains(str)){ v.add(str); for(int i = 0;i<str.length();i++){ String c = String.valueOf(str.charAt(i)); permutations.add(str.substring(i+1) + c + str.substring(0,i)); } } } return v; }


Podemos usar factorial para encontrar cuántas cadenas empezaron con una letra en particular.

Ejemplo: tomar la entrada abcd . (3!) == 6 cadenas comenzarán con cada letra de abcd .

static public int facts(int x){ int sum = 1; for (int i = 1; i < x; i++) { sum *= (i+1); } return sum; } public static void permutation(String str) { char[] str2 = str.toCharArray(); int n = str2.length; int permutation = 0; if (n == 1) { System.out.println(str2[0]); } else if (n == 2) { System.out.println(str2[0] + "" + str2[1]); System.out.println(str2[1] + "" + str2[0]); } else { for (int i = 0; i < n; i++) { if (true) { char[] str3 = str.toCharArray(); char temp = str3[i]; str3[i] = str3[0]; str3[0] = temp; str2 = str3; } for (int j = 1, count = 0; count < facts(n-1); j++, count++) { if (j != n-1) { char temp1 = str2[j+1]; str2[j+1] = str2[j]; str2[j] = temp1; } else { char temp1 = str2[n-1]; str2[n-1] = str2[1]; str2[1] = temp1; j = 1; } // end of else block permutation++; System.out.print("permutation " + permutation + " is -> "); for (int k = 0; k < n; k++) { System.out.print(str2[k]); } // end of loop k System.out.println(); } // end of loop j } // end of loop i } }


Todos los colaboradores anteriores han hecho un gran trabajo explicando y proporcionando el código. Pensé que debería compartir este enfoque también porque podría ayudar a alguien también. La solución se basa en ( algoritmo de montones )

Un par de cosas:

  1. Observe que el último elemento que se muestra en Excel es solo para ayudarlo a visualizar mejor la lógica. Por lo tanto, los valores reales en la última columna serían 2,1,0 (si tuviéramos que ejecutar el código porque estamos tratando con matrices y las matrices comienzan con 0).

  2. El algoritmo de intercambio se basa en valores pares o impares de la posición actual. Es muy autoexplicativo si observa dónde se llama al método de intercambio. Puede ver lo que está pasando.

Esto es lo que pasa:

public static void main(String[] args) { String ourword = "abc"; String[] ourArray = ourword.split(""); permute(ourArray, ourArray.length); } private static void swap(String[] ourarray, int right, int left) { String temp = ourarray[right]; ourarray[right] = ourarray[left]; ourarray[left] = temp; } public static void 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 position if (currentPosition % 2 == 1) { swap(ourArray, 0, currentPosition - 1); } else { swap(ourArray, i, currentPosition - 1); } } } }


Una de las soluciones simples podría ser simplemente intercambiar recursivamente los caracteres utilizando dos punteros.

public static void main(String[] args) { String str="abcdefgh"; perm(str); } public static void perm(String str) { char[] char_arr=str.toCharArray(); helper(char_arr,0); } public static void helper(char[] char_arr, int i) { if(i==char_arr.length-1) { // print the shuffled string String str=""; for(int j=0; j<char_arr.length; j++) { str=str+char_arr[j]; } System.out.println(str); } else { for(int j=i; j<char_arr.length; j++) { char tmp = char_arr[i]; char_arr[i] = char_arr[j]; char_arr[j] = tmp; helper(char_arr,i+1); char tmp1 = char_arr[i]; char_arr[i] = char_arr[j]; char_arr[j] = tmp1; } } }


Una solución muy básica en Java es usar recursion + Set (para evitar repeticiones) si desea almacenar y devolver las cadenas de solución:

public static Set<String> generatePerm(String input) { Set<String> set = new HashSet<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; }


Usa la recursividad.

cuando la entrada es una cadena vacía, la única permutación es una cadena vacía. Intente para cada una de las letras de la cadena haciéndola como la primera letra y luego encuentre todas las permutaciones de las letras restantes mediante una llamada recursiva.

import java.util.ArrayList; import java.util.List; class Permutation { private static List<String> permutation(String prefix, String str) { List<String> permutations = new ArrayList<>(); 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; } public static void main(String[] args) { List<String> perms = permutation("", "abcd"); String[] array = new String[perms.size()]; for (int i = 0; i < perms.size(); i++) { array[i] = perms.get(i); } int x = array.length; for (final String anArray : array) { System.out.println(anArray); } } }


Usa la recursividad.

  • Pruebe cada una de las letras como la primera letra y luego encuentre todas las permutaciones de las letras restantes mediante una llamada recursiva.
  • El caso base es cuando la entrada es una cadena vacía, la única permutación es la cadena vacía.

Vamos a usar la entrada abc como ejemplo.

Comience solo con el último elemento ( c ) en un conjunto ( ["c"] ), luego agregue el segundo último elemento ( b ) a su parte frontal, final y todas las posiciones posibles en el medio, haciéndolo ["bc", "cb"] y luego, de la misma manera, agregará el siguiente elemento de la parte posterior ( a ) a cada cadena en el conjunto que lo hace:

"a" + "bc" = ["abc", "bac", "bca"] and "a" + "cb" = ["acb" ,"cab", "cba"]

Así toda la permutación:

["abc", "bac", "bca","acb" ,"cab", "cba"]

Código:

public class Test { static Set<String> permutations; static Set<String> result = new HashSet<String>(); public static Set<String> permutation(String string) { permutations = new HashSet<String>(); int n = string.length(); for (int i = n - 1; i >= 0; i--) { shuffle(string.charAt(i)); } return permutations; } private static void 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 = new StringBuilder(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 = new HashSet<String>(); } } public static void 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()); } } }


esto funcionó para mí ..

import java.util.Arrays; public class StringPermutations{ public static void main(String args[]) { String inputString = "ABC"; permute(inputString.toCharArray(), 0, inputString.length()-1); } public static void permute(char[] ary, int startIndex, int endIndex) { if(startIndex == endIndex){ System.out.println(String.valueOf(ary)); }else{ for(int i=startIndex;i<=endIndex;i++) { swap(ary, startIndex, i ); permute(ary, startIndex+1, endIndex); swap(ary, startIndex, i ); } } } public static void swap(char[] ary, int x, int y) { char temp = ary[x]; ary[x] = ary[y]; ary[y] = temp; } }


implementación 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'','''')


La recursión no es necesaria, incluso si puede calcular cualquier permutación directamente , esta solución utiliza genéricos para permutar cualquier matriz.

Here hay una buena información sobre este algoritmo.

Para los desarrolladores de C # here es una implementación más útil.

public static void 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); } } private static void printPermutation(Character[] permutation) { for (int i = 0; i < permutation.length; i++) { System.out.print(permutation[i]); } System.out.println(); }

Este algoritmo tiene O (N) complejidad de tiempo y espacio para calcular cada permutación .

public class Permutation { public static <T> T[] getPermutation(long permutationNumber, T[] array, long[] factorials) { int[] sequence = generateSequence(permutationNumber, array.length - 1, factorials); T[] permutation = generatePermutation(array, sequence); return permutation; } public static <T> T[] generatePermutation(T[] array, int[] sequence) { T[] clone = array.clone(); for (int i = 0; i < clone.length - 1; i++) { swap(clone, i, i + sequence[i]); } return clone; } private static int[] generateSequence(long permutationNumber, int size, long[] factorials) { int[] sequence = new int[size]; for (int j = 0; j < sequence.length; j++) { long factorial = factorials[sequence.length - j]; sequence[j] = (int) (permutationNumber / factorial); permutationNumber = (int) (permutationNumber % factorial); } return sequence; } private static <T> void swap(T[] array, int i, int j) { T t = array[i]; array[i] = array[j]; array[j] = t; } public static long[] getFactorials(int length) { long[] factorials = new long[length]; long factor = 1; for (int i = 0; i < length; i++) { factor *= i <= 1 ? 1 : i; factorials[i] = factor; } return factorials; } }


Permutación de cuerdas:

public static void main(String args[]) { permu(0,"ABCD"); } static void permu(int fixed,String s) { char[] chr=s.toCharArray(); if(fixed==s.length()) System.out.println(s); for(int i=fixed;i<s.length();i++) { char c=chr[i]; chr[i]=chr[fixed]; chr[fixed]=c; permu(fixed+1,new String(chr)); } }


Esta es una solución de C:

#include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> char* addLetter(char* string, char *c) { char* result = malloc(sizeof(string) + 2); strcpy(result, string); strncat(result, c, 1); return result; } char* removeLetter(char* string, char *c) { char* result = malloc(sizeof(string)); int j = 0; for (int i = 0; i < strlen(string); i++) { if (string[i] != *c) { result[j++] = string[i]; } } result[j] = ''/0''; return result; } void makeAnagram(char *anagram, char *letters) { if (*letters == ''/0'') { printf("%s/n", anagram); return; } char *c = letters; while (*c != ''/0'') { makeAnagram(addLetter(anagram, c), removeLetter(letters, c)); c++; } } int main() { makeAnagram("", "computer"); return 0; }


Otra forma sencilla es recorrer la cadena, seleccionar el carácter que aún no se usa y colocarlo en un búfer, continuar el ciclo hasta que el tamaño del búfer sea igual a la longitud de la cadena. Me gusta esta solución de seguimiento de vuelta mejor porque:

  1. Fácil de entender
  2. Fácil de evitar la duplicación.
  3. La salida está ordenada.

Aquí está el código java:

List<String> permute(String str) { if (str == null) { return null; } char[] chars = str.toCharArray(); boolean[] used = new boolean[chars.length]; List<String> res = new ArrayList<String>(); StringBuilder sb = new StringBuilder(); 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 duplicates if (i > 0 && chars[i] == chars[i - 1] && !used[i - 1]) { continue; } // pick the character that has not used yet if (!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 salida: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}

Notó que la salida está ordenada, y no hay resultados duplicados.


/* * eg: abc =>{a,bc},{b,ac},{c,ab} * =>{ca,b},{cb,a} * =>cba,cab * =>{ba,c},{bc,a} * =>bca,bac * =>{ab,c},{ac,b} * =>acb,abc */ public void nonRecpermute(String prefix, String word) { String[] currentstr ={prefix,word}; Stack<String[]> stack = new Stack<String[]>(); stack.add(currentstr); while(!stack.isEmpty()) { currentstr = stack.pop(); String currentPrefix = currentstr[0]; String currentWord = currentstr[1]; if(currentWord.equals("")) { System.out.println("Word ="+currentPrefix); } for(int i=0;i<currentWord.length();i++) { String[] newstr = new String[2]; newstr[0]=currentPrefix + String.valueOf(currentWord.charAt(i)); newstr[1] = currentWord.substring(0, i); if(i<currentWord.length()-1) { newstr[1] = newstr[1]+currentWord.substring(i+1); } stack.push(newstr); } } }


/** Returns an array list containing all * permutations of the characters in s. */ public static ArrayList<String> permute(String s) { ArrayList<String> perms = new ArrayList<>(); 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 string String 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; }


//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 */ public class StringPermute { static String str; static String word; static int top1 = -1; static int top2 = -1; static String[] stringArray1; static String[] stringArray2; static int strlength = 0; public static void main(String[] args) throws IOException { System.out.println("Enter String : "); InputStreamReader isr = new InputStreamReader(System.in); BufferedReader bfr = new BufferedReader(isr); str = bfr.readLine(); word = str; strlength = str.length(); int n = 1; for (int i = 1; i <= strlength; i++) { n = n * i; } stringArray1 = new String[n]; stringArray2 = new String[n]; push(word, 1); doPermute(); display(); } public static void push(String word, int x) { if (x == 1) stringArray1[++top1] = word; else stringArray2[++top2] = word; } public static String pop(int x) { if (x == 1) return stringArray1[top1--]; else return stringArray2[top2--]; } public static void doPermute() { for (int j = strlength; j >= 2; j--) popper(j); } public static void popper(int length) { // pop from stack1 , rotate each word n times and push to stack 2 if (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 1 else { while (top2 > -1) { word = pop(2); for (int j = 0; j < length; j++) { rotate(length); push(word, 1); } } } } public static void rotate(int position) { char[] charstring = new char[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 = new String(charstring).trim(); } public static void display() { int top; if (top1 > -1) { while (top1 > -1) System.out.println(stringArray1[top1--]); } else { while (top2 > -1) System.out.println(stringArray2[top2--]); } } }


import java.io.IOException; import java.util.ArrayList; import java.util.Scanner; public class hello { public static void main(String[] args) throws IOException { hello h = new hello(); h.printcomp(); } int fact=1; public void factrec(int a,int k){ if(a>=k) {fact=fact*k; k++; factrec(a,k); } else {System.out.println("The string will have "+fact+" permutations"); } } public void printcomp(){ String str; int k; Scanner in = new Scanner(System.in); System.out.println("enter the string whose permutations has to b found"); str=in.next(); k=str.length(); factrec(k,1); String[] arr =new String[fact]; char[] array = str.toCharArray(); while(p<fact) printcomprec(k,array,arr); // if incase u need array containing all the permutation use this //for(int d=0;d<fact;d++) //System.out.println(arr[d]); } int y=1; int p = 0; int g=1; int z = 0; public void printcomprec(int k,char array[],String arr[]){ for (int l = 0; l < k; l++) { for (int b=0;b<k-1;b++){ for (int i=1; i<k-g; i++) { char temp; String stri = ""; temp = array[i]; array[i] = array[i + g]; array[i + g] = temp; for (int j = 0; j < k; j++) stri += array[j]; arr[z] = stri; System.out.println(arr[z] + " " + p++); z++; } } char temp; temp=array[0]; array[0]=array[y]; array[y]=temp; if (y >= k-1) y=y-(k-1); else y++; } if (g >= k-1) g=1; else g++; } }


public static void permutation(String str) { permutation("", str); } private static void 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)); } }

(a través de Introducción a la Programación en Java )