Une tâche courante dans la programmation des interviews (pas de mon expérience des interviews cependant) est de prendre une chaîne ou un entier et de lister toutes les permutations possibles.
Y a-t-il un exemple de la façon dont cela est fait et de la logique derrière la résolution d'un tel problème?
J'ai vu quelques extraits de code mais ils n'étaient pas bien commentés / expliqués et donc difficiles à suivre.
c#
algorithm
permutation
GurdeepS
la source
la source
Réponses:
Tout d'abord: ça sent la récursion bien sûr!
Puisque vous vouliez aussi connaître le principe, j'ai fait de mon mieux pour l'expliquer en langage humain. Je pense que la récursivité est très facile la plupart du temps. Vous n'avez qu'à saisir deux étapes:
En langage humain :
J'ai trouvé le pseudocode sur http://www.programmersheaven.com/mb/Algorithms/369713/369713/permutation-algorithm-help/ :
C #
OK, et quelque chose de plus élaboré (et puisqu'il est étiqueté c #), de http://radio.weblogs.com/0111551/stories/2002/10/14/permutations.html : Plutôt long, mais j'ai décidé de le copier de toute façon, le message ne dépend donc pas de l'original.
ABC, ACB, BAC, BCA, CAB, CBA.
Code:
la source
Swap(ref list[k], ref list[i]);
) est inutile.(a[x], a[y]) = (a[y], a[x]);
Ce n'est que deux lignes de code si LINQ est autorisé à utiliser. Veuillez voir ma réponse ici .
ÉDITER
Voici ma fonction générique qui peut renvoyer toutes les permutations (pas les combinaisons) à partir d'une liste de T:
Exemple:
Sortie - une liste de listes d'entiers:
Comme cette fonction utilise LINQ, elle nécessite .net 3.5 ou supérieur.
la source
const string s = "HALLOWEEN";
var result = GetPermutations(Enumerable.Range(0, s.Length), s.Length).Select(t => t.Select(i => s[i]));
Ici, j'ai trouvé la solution. Il a été écrit en Java, mais je l'ai converti en C #. J'espère que cela vous aidera.
Voici le code en C #:
la source
La récursivité n'est pas nécessaire, voici de bonnes informations sur cette solution.
J'utilise cet algorithme depuis des années, il a une complexité temporelle et spatiale O (N) pour calculer chaque permutation .
la source
O(N-1)
pour la séquence etO(N)
pour les swaps, ce qui estO(N)
. Et j'utilise toujours ceci en production mais avec un refactor pour générer une seule permutation comme:GetPermutation(i)
où0 <= i <= N!-1
. Je serai heureux d'utiliser quelque chose avec de meilleures performances que celle-ci, alors soyez libre d'appeler une référence pour quelque chose de mieux, la plupart des utilisations alternativesO(N!)
en mémoire afin que vous puissiez vérifier cela aussi.Vous pouvez écrire votre fonction d'échange pour permuter les caractères.
Ceci doit être appelé comme permute (string, 0);
la source
Tout d'abord, les ensembles ont des permutations, pas des chaînes ou des entiers, donc je suppose simplement que vous voulez dire «l'ensemble des caractères d'une chaîne».
Notez qu'un ensemble de taille n a n! n-permutations.
Le pseudocode suivant (de Wikipedia), appelé avec k = 1 ... n! donnera toutes les permutations:
Voici le code Python équivalent (pour les index de tableau basés sur 0):
la source
k := k / j;
ça fait.Version légèrement modifiée en C # qui donne les permutations nécessaires dans un tableau de type ANY.
la source
Permutations(vals).ToArray()
vous vous retrouvez avec N références au même tableau. Si vous voulez pouvoir stocker les résultats, vous devez créer manuellement une copie. Par exemplePermutations(values).Select(v => (T[])v.Clone())
la source
J'ai aimé l' approche FBryant87 car elle est simple. Malheureusement, comme beaucoup d'autres «solutions», elle n'offre pas toutes les permutations ou par exemple un entier s'il contient le même chiffre plus d'une fois. Prenons l'exemple de 656123. La ligne:
Sauf à l' aide entraînera toutes les occurrences à supprimer, à savoir quand c = 6, deux chiffres sont retirés et il nous reste par exemple 5123. Comme aucune des solutions que j'ai essayé résolu ce problème, j'ai décidé d'essayer de le résoudre par moi - même FBryant87 d » code comme base. Voici ce que j'ai proposé:
Je supprime simplement la première occurrence trouvée en utilisant .Remove et .IndexOf. Semble fonctionner comme prévu pour mon utilisation au moins. Je suis sûr que cela pourrait être rendu plus intelligent.
Une chose à noter cependant: la liste résultante peut contenir des doublons, alors assurez-vous que la méthode retourne par exemple un HashSet à la place ou supprimez les doublons après le retour en utilisant la méthode de votre choix.
la source
Voici un bon article couvrant trois algorithmes pour trouver toutes les permutations, dont un pour trouver la prochaine permutation.
http://www.cut-the-knot.org/do_you_know/AllPerm.shtml
C ++ et Python ont respectivement des fonctions intégrées next_permutation et itertools.permutations .
la source
Voici une implémentation F # purement fonctionnelle:
Les performances peuvent être grandement améliorées en modifiant le swap pour tirer parti de la nature mutable des tableaux CLR, mais cette implémentation est thread-safe en ce qui concerne le tableau source et cela peut être souhaitable dans certains contextes. De plus, pour les tableaux de plus de 16 éléments, int doit être remplacé par des types avec une précision supérieure / arbitraire car factorielle 17 entraîne un débordement int32.
la source
Voici une solution simple en c # utilisant la récursivité,
la source
Voici une fonction de permutation facile à comprendre pour les chaînes et les entiers en entrée. Avec cela, vous pouvez même définir votre longueur de sortie (qui, dans le cas normal, est égale à la longueur d'entrée)
Chaîne
et pour Integer, changez simplement la méthode de l'appelant et MakePermutations () reste inchangé:
exemple 1: GetAllPermutations ("abc", 3); "abc" "acb" "bac" "bca" "cab" "cba"
exemple 2: GetAllPermutations ("abcd", 2); "ab" "ac" "ad" "ba" "bc" "bd" "ca" "cb" "cd" "da" "db" "dc"
exemple 3: GetAllPermutations (486,2); 48 46 84 86 64 68
la source
Voici la fonction qui affichera toutes les permutations. Cette fonction implémente la logique expliquée par peter.
la source
Voici ma mise en œuvre de la permutation. Ne vous inquiétez pas des noms de variables, car je le faisais pour le plaisir :)
la source
Voici un exemple de haut niveau que j'ai écrit et qui illustre l' explication du langage humain que Peter a donnée:
la source
Si les performances et la mémoire sont un problème, je suggère cette implémentation très efficace. Selon l'algorithme de Heap sur Wikipedia , il devrait être le plus rapide. J'espère qu'il répondra à vos besoins :-)!
Juste comme comparaison de cela avec une implémentation Linq pour 10! (code inclus):
Linq: 36288000 articles en 50051 millisecs
la source
Voici ma solution en JavaScript (NodeJS). L'idée principale est de prendre un élément à la fois, de le «supprimer» de la chaîne, de faire varier le reste des caractères et d'insérer l'élément au début.
Et voici les tests:
la source
Voici la solution la plus simple à laquelle je puisse penser:
La
distribute
fonction prend un nouvel élémente
et unen
liste d'éléments et renvoie une liste den+1
listes dont chacune a étée
insérée à un endroit différent. Par exemple, insérer10
à chacun des quatre endroits possibles dans la liste[1;2;3]
:La
permute
fonction se replie sur chaque élément à son tour en répartissant les permutations accumulées jusqu'à présent, aboutissant à toutes les permutations. Par exemple, les 6 permutations de la liste[1;2;3]
:Modification de l'
fold
unescan
afin de maintenir les accumulateurs intermédiaires éclaire sur la façon dont les permutations sont générés un élément à la fois:la source
Répertorie les permutations d'une chaîne. Évite la duplication lorsque les caractères sont répétés:
la source
En s'appuyant sur la solution de @ Peter, voici une version qui déclare une
Permutations()
méthode d'extension simple de style LINQ qui fonctionne sur toutIEnumerable<T>
.Utilisation (sur l'exemple de caractères de chaîne):
Les sorties:
Ou sur tout autre type de collection:
Les sorties:
la source
Voici la fonction qui imprimera toutes les permutations de manière récursive.
la source
la source
Voici une réponse C # qui est un peu simplifiée.
Production:
la source
C'est ma solution qu'il m'est facile de comprendre
la source
Voici une autre implémentation de l'algo mentionné.
la source
new Permutation().GenerateFor("aba")
sortiesstring[4] { "ab", "baa", "baa", "ab" }
la source
la source