Quelle est une manière élégante de trouver toutes les permutations d'une chaîne. Par exemple, la permutation pour ba
, serait ba
et ab
, mais qu'en est-il de la chaîne plus longue comme abcdefgh
? Existe-t-il un exemple d'implémentation Java?
418
Réponses:
(via Introduction à la programmation en Java )
la source
n==0
, vous pouvez arrêter un niveau plus tôtn==1
et imprimerprefix + str
.Utilisez la récursivité.
la source
Voici ma solution qui est basée sur l'idée du livre "Cracking the Coding Interview" (P54):
Exécution de la sortie de la chaîne "abcd":
Étape 1: fusionnez [a] et b: [ba, ab]
Étape 2: fusionnez [ba, ab] et c: [cba, bca, bac, cab, acb, abc]
Étape 3: fusionner [cba, bca, bac, cab, acb, abc] et 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]
la source
De toutes les solutions proposées ici et dans d'autres forums, j'ai le plus apprécié Mark Byers. Cette description m'a en fait fait réfléchir et coder moi-même. Dommage que je ne puisse pas voter contre sa solution car je suis novice.
Quoi qu'il en soit, voici ma mise en œuvre de sa description
Je préfère cette solution avant la première dans ce fil parce que cette solution utilise StringBuffer. Je ne dirais pas que ma solution ne crée aucune chaîne temporaire (elle le fait en fait à l'
system.out.println
endroit où letoString()
StringBuffer est appelé). Mais je pense que c'est mieux que la première solution où trop de littéraux de chaînes sont créés. Peut-être qu'un gars de la performance peut évaluer cela en termes de `` mémoire '' (pour le `` temps '', il est déjà en retard en raison de ce `` swap '' supplémentaire)la source
if(index == str.length())
etdoPerm(str, index + 1);
? LecurrPos
semble inutile ici.Une solution très basique en Java consiste à utiliser récursivité + Set (pour éviter les répétitions) si vous souhaitez stocker et renvoyer les chaînes de solution:
la source
Tous les contributeurs précédents ont fait un excellent travail en expliquant et en fournissant le code. J'ai pensé que je devrais aussi partager cette approche car cela pourrait aider quelqu'un aussi. La solution est basée sur ( algorithme de tas )
Quelques choses:
Remarquez que le dernier élément décrit dans Excel est juste pour vous aider à mieux visualiser la logique. Ainsi, les valeurs réelles dans la dernière colonne seraient 2,1,0 (si nous devions exécuter le code car nous avons affaire à des tableaux et les tableaux commencent par 0).
L'algorithme de permutation se produit en fonction des valeurs paires ou impaires de la position actuelle. Il est très explicite si vous regardez où la méthode de swap est appelée. Vous pouvez voir ce qui se passe.
Voici ce qui se passe:
la source
Celui-ci est sans récursivité
la source
System.out.println(permute("AABBC").size());
affiche 45, mais en fait 5! = 120Utilisons l'entrée
abc
comme exemple.Commencez avec juste le dernier élément (
c
) dans un ensemble (["c"]
), puis ajoutez l'avant-dernier élément (b
) à son avant, à son extrémité et à toutes les positions possibles au milieu, ce qui en fait["bc", "cb"]
, puis de la même manière, il ajoutera l'élément suivant de l'arrière (a
) à chaque chaîne de l'ensemble, ce qui en fait:Ainsi toute permutation:
Code:
la source
Eh bien voici une solution O (n!) Élégante et non récursive:
la source
L'une des solutions les plus simples pourrait être de continuer à échanger les caractères récursivement à l'aide de deux pointeurs.
la source
implémentation de python
la source
cela a fonctionné pour moi ..
la source
Utilisez la récursivité.
lorsque l'entrée est une chaîne vide, la seule permutation est une chaîne vide.Essayez pour chacune des lettres de la chaîne en la créant comme première lettre, puis recherchez toutes les permutations des lettres restantes à l'aide d'un appel récursif.
la source
Permettez-moi d'essayer de résoudre ce problème avec Kotlin:
Concept de base: décomposer la longue liste en une liste plus petite + récursivité
Réponse longue avec liste d'exemples [1, 2, 3, 4]:
Même pour une liste de 4, il est déjà un peu déroutant d'essayer de répertorier toutes les permutations possibles dans votre tête, et ce que nous devons faire est exactement d'éviter cela. Il est facile pour nous de comprendre comment faire toutes les permutations de la liste des tailles 0, 1 et 2, donc tout ce que nous devons faire est de les décomposer en l'une de ces tailles et de les combiner correctement. Imaginez une machine à jackpot: cet algorithme commencera à tourner de la droite vers la gauche et notera
la source
la source
la source
Voici une solution récursive minimaliste simple en Java:
la source
Nous pouvons utiliser factorielle pour trouver le nombre de chaînes commençant par une lettre particulière.
Exemple: prenez l'entrée
abcd
.(3!) == 6
les chaînes commenceront par chaque lettre deabcd
.la source
C'est ce que j'ai fait grâce à une compréhension de base des permutations et des appels de fonction récursifs. Prend un peu de temps mais cela se fait de façon indépendante.
qui génère une sortie en tant que
[abc, acb, bac, bca, cab, cba]
.La logique de base derrière elle est
Pour chaque personnage, considérez-le comme le 1er personnage et trouvez les combinaisons des caractères restants. par exemple
[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}
Et puis récursivement en appelant chacun
[bc]
,[ac]
et[ab]
indépendamment.la source
Implémentation Java sans récursivité
la source
// insère chaque caractère dans une liste de tableaux
la source
la source
Une autre façon simple est de parcourir la chaîne, de choisir le caractère qui n'est pas encore utilisé et de le mettre dans un tampon, de continuer la boucle jusqu'à ce que la taille du tampon soit égale à la longueur de la chaîne. J'aime mieux cette solution de suivi arrière car:
Voici le code java:
Chaîne d'entrée: 1231
Liste de sortie: {1123, 1132, 1213, 1231, 1312, 1321, 2113, 2131, 2311, 3112, 3121, 3211}
Remarqué que la sortie est triée et qu'il n'y a pas de résultat en double.
la source
Récursivité n'est pas nécessaire, même si vous pouvez calculer directement n'importe quelle permutation , cette solution utilise des génériques pour permuter n'importe quel tableau.
Voici une bonne information sur cet algorithme.
Pour les développeurs C # voici une implémentation plus utile.
Cet algorithme a O (N) complexité temporelle et spatiale pour calculer chaque permutation .
la source
Permutation de chaîne:
la source
Voici une autre méthode plus simple de permutation d'une chaîne.
la source
Une implémentation Java pour imprimer toutes les permutations d'une chaîne donnée en tenant compte des caractères en double et imprime uniquement des caractères uniques est la suivante:
la source
la source
Cela peut être fait de manière itérative en insérant simplement chaque lettre de la chaîne à son tour dans tous les emplacements des résultats partiels précédents.
Nous commençons par
[A]
, qui , avecB
devient[BA, AB]
, etC
,[CBA, BCA, BAC, CAB, etc]
.Le temps d'exécution serait
O(n!)
, ce qui, pour le cas de testABCD
, est1 x 2 x 3 x 4
.Dans le produit ci-dessus, le
1
est pourA
, le2
est pourB
, etc.Échantillon de fléchettes:
la source
Voici une implémentation java:
http://ideone.com/nWPb3k
la source