Rapide permutation -> nombre> permutation de cartographie des algorithmes
J'ai de n éléments. Pour le bien d'un exemple, disons, 7 éléments, 1234567. Je sais qu'il y a 7! = 5040 permutations possibles de ces 7 éléments.
Je veux un algorithme rapide composée de deux fonctions:
f(nombre) cartes un nombre entre 0 et 5039 à un unique permutation, et
f'(permutation) les cartes de la permutation de retour pour le nombre qu'il a été généré à partir.
Je ne m'inquiète pas à propos de la correspondance entre le numéro et la permutation, fournissant à chaque permutation a son propre numéro unique.
Ainsi, par exemple, je pourrais avoir les fonctions où
f(0) = '1234567'
f'('1234567') = 0
L'algorithme le plus rapide qui vient à l'esprit consiste à énumérer toutes les permutations et de créer une table de recherche dans les deux directions, de sorte que, une fois que les tables sont créées, f(0) O(1) et f('1234567") devrait être une recherche sur une chaîne de caractères. Cependant, c'est la mémoire de la faim, en particulier lorsque n devient grand.
Quelqu'un peut proposer un autre algorithme de travailler rapidement et sans la mémoire inconvénient?
- Bien que l'algorithme ci-dessous est très complet, vous avez bien remarquer que l'algorithme le plus rapide est une table de recherche. Vous êtes vraiment pas à parler de " autant que de mémoire, même si bien sûr, cela dépend de votre système d' & plate-forme. Mais si une table de recherche est suffisant, et si c'est une application du monde réel, de l'utiliser. Fast & simple!
- Vous le dire, mais n n'a pas à être très grand pour elle d'être bête. Pour 12 éléments, le 12! est 479,001,600 permutations. C'est une grande table de!
- Ne pas se tromper par les différents postes de l'utilisation n de sens différent. Certains n stand pour la longueur de la chaîne, certains n stand pour le nombre de permutations possibles. Ne pas aveuglément comparer le big O notion. -- Retardataires être avertir -- –
Vous devez vous connecter pour publier un commentaire.
Pour décrire une permutation de n éléments, vous voyez que pour la position que le premier élément se termine, vous avez n possibilités, de sorte que vous pouvez décrire ce avec un nombre entre 0 et n-1. Pour le poste que l'élément suivant se termine, vous avez n-1 possibilités, de sorte que vous pouvez décrire ce avec un nombre entre 0 et n-2.
Et ainsi de suite jusqu'à ce que vous avez des n nombres.
Comme un exemple pour n = 5, envisager la permutation qui apporte
abcde
àcaebd
.a
, le premier élément, termine à la deuxième position, nous avons donc affecter l'indice de 1.b
termine à la quatrième position, ce qui serait l'indice 3, mais c'est le tiers restant, de sorte que nous lui attribuons 2.c
termine à la première position résiduelle, qui est toujours 0.d
termine à la dernière position (des deux seules places restantes) est 1.e
termine à la seule position, indexés au 0.Nous avons donc l'index de la séquence {1, 2, 0, 1, 0}.
Maintenant, vous savez que, par exemple, dans un nombre binaire, 'xyz' z + 2y + 4x. Pour un nombre décimal,
c'est z + 10y + 100x. Chaque chiffre est multiplié par un peu de poids, et les résultats sont additionnés. Le modèle évident dans le poids est bien sûr que le poids est w = b^k, avec b la base du nombre et k l'indice du chiffre. (Je vais toujours compter chiffres à partir de la droite et commençant à l'index 0 du chiffre droite. De même, quand je parle de la 'première' chiffres, je veux dire la plus à droite.)
La raison pourquoi le poids des chiffres suivez ce modèle est que le plus grand nombre qui peut être représenté par les chiffres de 0 à k doit être exactement 1 inférieur au plus petit nombre qui peut être représenté en utilisant uniquement des chiffres k+1. En binaire, 0111 doit être inférieur à celui de 1000. En décimal, 099999 doit être inférieur à celui de 100000.
Codage de la variable de la base de
L'espacement entre les autres numéros étant exactement 1 est la loi la plus importante. Sachant cela, nous pouvons représenter notre index de la séquence par un variable-nombre de base. La base pour chaque chiffre est la quantité de possibilités différentes pour ce chiffre. Pour chaque chiffre décimal a 10 possibilités, pour que notre système le chiffre droite aurait 1 de la possibilité et de l'extrême gauche en aura n possibilités. Mais depuis que le chiffre droite (le dernier numéro de notre séquence) est toujours égal à 0, nous la laisser. Cela signifie que nous sommes à gauche avec des bases de 2 à n. En général, la k-ième chiffre aura de la base b[k] = k + 2. La valeur la plus élevée autorisée pour les chiffres en k h[k] = b[k] - 1 = k + 1.
Notre règle concernant le poids w[k] de chiffres exige que la somme de h[i] * w[i], où i va de i = 0 à i = k, est égal à 1 * w[k+1]. A déclaré de manière récurrente, w[k+1] = w[k] + h[k] * w[k] = w[k]*h[k] + 1). Le premier poids w[0] doit toujours être de 1. A partir de là, nous avons les valeurs suivantes:
(Le rapport général w[k-1] = k! est facilement prouvé par induction.)
Le nombre nous obtenir de la conversion de notre séquence sera alors la somme de la s[k] * w[k], avec k variant de 0 à n-1. Ici, s[k] est le k-ième (à l'extrême droite, en commençant à 0) de l'élément de la séquence. Comme exemple, prenons notre {1, 2, 0, 1, 0}, avec la plus à droite de l'élément dépouillé comme mentionné avant: {1, 2, 0, 1}. Notre somme est 1 * 1 + 0 * 2 + 2 * 6 + 1 * 24 = 37.
Noter que si nous prenons le maximum de la position pour chaque indice, nous aurions {4, 3, 2, 1, 0}, et qui convertit à 119. Car les poids dans notre numéro de codage ont été choisis de sorte que nous n'avons pas ignorer tous les chiffres, tous les chiffres de 0 à 119 sont valides. Il y a précisément de 120 de ces, qui n! pour n = 5 dans notre exemple, précisément le nombre de permutations différentes. Donc vous pouvez voir notre codé numéros de spécifier complètement toutes les permutations possibles.
De décodage à partir d'une variable de la base
Le décodage est similaire à la conversion en binaire ou décimal. La commune de l'algorithme est: est-ce
Pour notre variable-nombre de base:
Ce décode correctement nos 37 retour à la {1, 2, 0, 1} (
sequence
serait{1, 0, 2, 1}
dans cet exemple de code, mais peu importe ... tant que vous index de façon appropriée). Nous avons juste besoin d'ajouter un 0 à l'extrémité droite (rappelez-vous le dernier élément a toujours qu'une seule possibilité pour son nouveau poste) revenir à notre séquence d'origine {1, 2, 0, 1, 0}.Permutant une liste à l'aide d'un index de séquence
Vous pouvez utiliser l'algorithme ci-dessous pour permuter une liste en fonction d'un indice spécifique de la séquence. C'est un O(n2) de l'algorithme, malheureusement.
Représentation commune de permutations
Normalement, vous ne représenterait pas une permutation comme unintuitively comme nous l'avons fait, mais simplement par la position absolue de chaque élément après la permutation est appliquée. Notre exemple {1, 2, 0, 1, 0} pour
abcde
àcaebd
est normalement représenté par {1, 3, 0, 4, 2}. Chaque indice de 0 à 4 (ou en général, de 0 à n-1) se produit exactement une fois dans cette représentation.L'application d'une permutation dans cette forme, c'est facile:
En l'inversant est très similaire:
La conversion de notre représentation à la représentation commune
Notez que si nous prenons notre algorithme de permuter d'une liste à l'aide de notre index de la séquence, et de l'appliquer à l'identité de la permutation de {0, 1, 2, ..., n-1}, nous obtenons le inverse permutation, représentée dans la forme commune. ({2, 0, 4, 1, 3} dans notre exemple).
Pour obtenir le non-inversé premutation, nous appliquons l'algorithme de permutation j'ai juste montré:
Ou vous pouvez simplement appliquer la permutation directement, en utilisant l'inverse de la permutation de l'algorithme:
Noter que tous les algorithmes pour traiter les permutations dans la commune de la forme O(n), tout en appliquant une permutation dans notre forme est O(n2). Si vous avez besoin d'appliquer une permutation plusieurs fois, d'abord le convertir à la représentation commune.
1234
, f(4) = {0, 2, 0, 0} = 1342. Et f'(1423) = {0, 1 1, 0} = 3. Cet algorithme est vraiment inspirant. Je me demande qu'elle est l'œuvre originale de l'OP. j'ai étudié et analysé pendant un certain temps. Et je crois que c'est correct 🙂{1, 2, 0, 1, 0}
-->{1, 3, 0, 4, 2}
? Et vice-versa? Est-il possible? (par pas conversion entre{1, 2, 0, 1, 0}
<-->{C, A, E, B, D}
, qui a besoin de O(n^2).) Si notre "style" et "commun" ne sont pas convertibles, ils sont en fait deux choses distinctes, n'est-ce pas? Merci xJ'ai trouvé un algorithme O(n), voici une courte explication http://antoinecomeau.blogspot.ca/2014/07/mapping-between-permutations-and.html
La complexité peut être ramené à n*log(n), voir la section 10.1.1
("Le code de Lehmer (table d'inversion)", p.232ff) de la fxtbook:
http://www.jjj.de/fxt/#fxtbook
passez à la section 10.1.1.1 ("Calcul avec de grands tableaux" p.235) pour la méthode rapide.
L' (sous licence gpl, C++) du code est sur la même page web.
Chaque élément peut être dans l'un des sept postes. Pour décrire la position d'un élément, vous aurait besoin de trois bits. Cela signifie que vous pouvez stocker la position de tous les éléments en 32 bits valeur. C'est loin d'être efficace, puisque cette représentation serait à même de permettre tous les éléments pour être dans la même position, mais je crois que le bit de masquage doit être assez rapide.
Cependant, avec plus de 8 postes, vous aurez besoin de quelque chose de plus astucieux.
Cela arrive à être une fonction intégrée dans J:
Le problème est résolu. Cependant, je ne suis pas sûr que vous avez encore besoin de la solution, après toutes ces années. LOL, je viens de rejoindre ce site, donc ...
Vérifier mon Java Permutation de Classe. Vous pouvez baser sur un index pour obtenir un symbole de permutation, ou de donner un symbole de permutation puis obtenir l'indice.
Voici mon Premutation Classe
et voici ma Classe Principale pour montrer comment utiliser la classe.
Avoir du plaisir. 🙂
Vous pouvez encoder des permutations à l'aide d'un algorithme récursif. Si un N-permutation (certains l'ordre des numéros de {0,..,N-1}) est de la forme {x, ...} puis l'encoder comme x + N * l'encodage de la (N-1)-permutation représentés par des "..." sur les nombres {0, N-1} - {x}. Sonne comme une bouchée, voici un code:
Cet algorithme est O(n^2). Les points de Bonus si quelqu'un a un algorithme O(n).
Ce une question intéressante!
Si tous les éléments sont des nombres, vous pourriez envisager de les convertir à partir de chaînes de nombres réels. Alors vous seriez en mesure de trier toutes les permutations en les mettant dans l'ordre, et les placer dans un tableau. Après cela, vous seriez ouvert à l'un des différents algorithmes de recherche là-bas.
J'ai été trop vite dans ma réponse précédente (supprimé), j'ai la réponse réelle cependant. Il est fourni par un concept similaire, le factoradic, et est liée à des permutations (ma réponse liés à des combinaisons, je m'excuse pour la confusion). Je déteste juste poster le lien avec wikipédia, mais je writeup je l'ai fait y a quelques temps est inintelligible pour une raison quelconque. Donc, je peux développer sur cela plus tard si nécessaire.
Il y a un livre écrit sur ce sujet. Désolé, mais je ne me souviens pas le nom de celui-ci (vous trouverez très probablement à partir de wikipedia).
mais de toute façon j'ai écrit un python de mise en œuvre de ce système de recensement: http://kks.cabal.fi/Kombinaattori
Certains de il est en finnois, mais il suffit de copier le code et le nom des variables ...
Une question connexe est celle du calcul de l'inverse de la permutation, permutation qui permettra de rétablir la permutation des vecteurs de commande d'origine lorsque seule la matrice de permutation est connu. Voici le O(n) code (en PHP):
David Spector
Printemps De Logiciels
J'ai eu cette question exacte et pensé que je pourrais donner mon Python solution. Il est O(n^2).
C'est assez simple; après la génération de la factoradic représentation du nombre, je viens de prendre et de supprimer les caractères de la chaîne. La suppression de la chaîne est pourquoi c'est un O(n^2) solution.
Antoine solution est meilleure pour la performance.