Générer toutes les chaînes binaires de longueur n avec k bits
Quel est le meilleur algorithme pour trouver toutes les chaînes binaires de longueur n contenant k bits? Par exemple, si n=4 et k=3, il y a...
0111
1011
1101
1110
J'ai besoin d'un bon moyen pour générer ces donné tout n et tout k donc je préfère qu'on le fasse avec des chaînes.
- Pour la recherche. Faire une analyse sur la mise en correspondance d'exclusion certain nombre de graphiques et j'ai besoin d'un moyen de tester tous les possible de bord de suppressions de k arêtes.
- Si vous êtes inquiet au sujet de la performance (c'est à dire un grand n et k), vous voudrez sans doute envisager une programmation dynamique de l'approche.
- ... surtout si c'est faisable de faire, et de mettre en cache (memoise) les résultats de l', une partie du bord de suppression sur un sous-ensemble de votre graphique, plutôt que la première génération de toutes les chaînes et ensuite de faire des choses avec eux. Cela permettrait de booster vos performances considérablement.
- double possible de Création de plusieurs numéros avec un certain nombre de bits set
- en.wikipedia.org/wiki/Combinatorial_number_system
Vous devez vous connecter pour publier un commentaire.
Cette méthode permettra de générer tous les nombres entiers avec exactement N '1' bits.
De https://graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
w = v==0 ? 0 : t | ((((t & -t) / (v & -v)) >> 1) - 1);
empêche la division par zéro exception!Python
Explication:
Essentiellement, nous devons choisir les positions de l'1-bits. Il y a n façons de choisir k de choisir les k bits de n nombre total de bits. itertools est une belle module qui fait ça pour nous. itertools.combinaisons(range(n), k) feront le choix de k bits de [0, 1, 2 ... n-1] et puis c'est juste une question de construction de la chaîne de caractères donnée ces bits d'index.
Puisque vous n'êtes pas à l'aide de Python, regardez le pseudo-code pour itertools.combinaisons ici:
http://docs.python.org/library/itertools.html#itertools.combinations
Devrait être facile à mettre en œuvre dans n'importe quelle langue.
Oublier de mise en œuvre ("être fait avec des cordes" est évidemment un mise en œuvre question!) - pensez-l' algorithme, bon sang... tout comme dans, votre première BALISE, homme!
Ce que vous cherchez est toutes les combinaisons de K éléments d'un ensemble de N (les indices de 0 à N-1 , de l'ensemble de bits). C'est évidemment plus simple d'exprimer de manière récursive, par exemple, de pseudo:
c'est à dire, le premier élément est soit présente, soit absente: si présent, vous avez K-1 à gauche pour aller (à partir de la queue aka tout-mais-sapins), en cas d'absence, encore K laissée aller.
Pattern-matching langages fonctionnels comme SML ou Haskell peut être le meilleur pour exprimer ce pseudo-code (procédurales, comme mon grand amour Python, peut masquer le problème trop profondément en incluant trop riche en fonctionnalités, telles que la
itertools.combinations
, qui fait tout le travail dur pour vous et, par conséquent, se CACHE de vous!).De quoi êtes-vous le plus familier, pour cette raison-Régime, SML, Haskell, ...? Je serai heureux de traduire le pseudo-code ci-dessus pour vous. Je peux le faire dans des langages tels que Python aussi, bien sûr-mais puisque le but est de vous amener à comprendre la mécanique de ce devoir, je ne les utilise pas trop riche en fonctionnalités telles que la
itertools.combinations
, mais plutôt la récursivité (et récursivité-élimination, si nécessaire) sur plus évident primitives (comme la tête, la queue, et la concaténation). Mais s'il vous plaît laissez-nous savoir ce pseudo-comme la langue que vous êtes plus familier avec le! (Vous FAIRE comprendre que le problème de l'état est identique équipotent à "obtenir toutes les combinaisons de K éléments ou de la plage(N)", non?).Cette méthode C# renvoie un énumérateur qui crée toutes les combinaisons. Comme il crée les combinaisons que vous les énumérer, il n'utilise que l'espace de pile, de sorte qu'il n'est pas limité par l'espace mémoire dans le nombre de combinaisons qu'il peut créer.
C'est la première version que j'ai trouvé. Il est limité par l'espace de pile pour une longueur d'environ 2700:
C'est la deuxième version, qui utilise un binaire diviser plutôt que de diviser le premier caractère, de sorte qu'il utilise la pile de manière beaucoup plus efficace. C'est seulement limité par l'espace mémoire pour la chaîne qu'il crée à chaque itération, et je l'ai testé jusqu'à une longueur de 10000000:
Un problème avec beaucoup de standard de solutions à ce problème, c'est que l'ensemble des chaînes est généré et puis ceux-ci sont répétées à travers, ce qui peut épuiser la pile. Il devient vite encombrant pour tous, mais les plus petits ensembles. En outre, dans de nombreux cas, seule une partie de l'échantillonnage est nécessaire, mais la norme (récursif) des solutions généralement hacher le problème en morceaux qui sont fortement biaisée à une direction (par exemple. envisager toutes les solutions avec un zéro bit de début, puis toutes les solutions avec un bit de début).
Dans de nombreux cas, il serait plus souhaitable d'être en mesure de passer à une chaîne de bits (en spécifiant l'élément de sélection) à une fonction et revenir le lendemain chaîne de bits de manière à avoir un changement minime (ce qui est connu comme un Gris Code) et de disposer d'une représentation de tous les éléments.
Donald Knuth couvre une multitude d'algorithmes dans son Fascicule 3 BIS, l'article 7.2.1.3: Générer toutes les Combinaisons.
Il s'agit d'une approche pour la lutte contre l'itératif Gris algorithme de Code pour toutes les façons de choisir k éléments parmi n à http://answers.yahoo.com/question/index?qid=20081208224633AA0gdMl
avec un lien pour la finale de PHP code répertorié dans le commentaire (cliquez pour agrandir) au bas de la page.
Un algorithme qui devrait fonctionner:
Bonne chance!
En plus de façon générique, ci-dessous la fonction va vous donner tous les possibles de l'indice de combinaisons de N de choisir K un problème auquel vous pouvez ensuite appliquer à une chaîne ou de tout autre chose:
Python (style fonctionnel)
À l'aide de
python
'sitertools.combinations
vous pouvez générer tous les choix dek
notre den
et de cartographier ces choix à un tableau binaire avecreduce
Exemple d'utilisation:
Possible de 1,5-doublure:
.. où
k
est le nombre de1
s dans"0111"
.Le module itertools explique équivalents pour ses méthodes; voir l'équivalent pour le permutation de la méthode.
itertools.combinations
au lieuJe voudrais essayer de récursivité.
Il y a des chiffres n avec k d'entre eux 1s. Une autre façon de voir cela est de la séquence de k+1 slots avec la n-k 0 réparti entre eux. Qui est, (une course de 0 suivi par un 1) k fois, puis une autre course de 0s. Aucun de ces essais peut être de longueur nulle, mais la longueur totale doit être n-k.
La représenter comme un ensemble de k+1 entiers. Convertir une chaîne de caractères au bas de la récursivité.
De manière récursive appel à la profondeur n-k, une méthode qui incrémente un élément de la matrice avant un appel récursif et puis décrémente, k+1 fois.
À la profondeur de la n-k, la chaîne de sortie.
Il a été un moment depuis que j'ai fait en Java, donc il y a probablement quelques erreurs dans ce code, mais l'idée devrait fonctionner.
Sont des chaînes de caractères plus rapide qu'un tableau d'entiers? Toutes les solutions ajoutant à cordes probablement une copie de la chaîne à chaque itération.
Donc probablement le moyen le plus efficace serait un tableau de int ou char que vous ajoutez à. Java est efficace cultivables conteneurs, droit? Utilisez-le, si c'est plus rapide que string. Ou si BigInteger est efficace, c'est certainement compact, puisque chaque bit prend seulement un peu, pas tout un octet ou entier. Mais puis d'itérer sur les éléments dont vous avez besoin pour & masque un peu, et bitshift le masque à la prochaine position du bit. De manière sans doute plus lent, à moins que les compilateurs JIT sont bonnes à ces jours-ci.
Je post ce un un commentaire sur la question d'origine, mais mon karma n'est pas assez haut. Désolé.