Trouver toutes les combinaisons de bien-formé entre parenthèses
Ce m'est venue en parler à un ami et j'ai pensé que je voudrais vous demander ici, puisque c'est un problème intéressant et souhaitez en voir d'autres solutions.
La tâche est d'écrire une fonction entre Parenthèses(int n) qui imprime toutes les combinaisons de bien formé crochets à partir de 1...n. Pour les Crochets(3), la sortie serait
()
(()) ()()
((())) (()()) (())() ()(()) ()()()
- Personne ne sait pourquoi le nombre de bien-formé 2n crochets est C(2n, n) - C(2n, n+1). Je sais C(2n, n) n'est évidemment plus le comptage nous avons donc besoin de soustraire quelque chose, mais je ne vois pas comment quelque chose est C(2n, n+1)
Vous devez vous connecter pour publier un commentaire.
A pris une fissure à elle.. C# aussi.
La récursivité est en train de profiter du fait que vous ne pouvez jamais ajouter plus de l'ouverture des crochets que le nombre de paires, et vous ne pouvez pas ajouter plus de crochets de clôture de l'ouverture des crochets..
close<pairs
+1Le nombre de combinaisons possibles est la Catalan nombre de N paires de C(n).
Ce problème a été discuté sur le joelonsoftware.com forums assez exentsively y compris itératif et récursif et itératif/bitshifting solutions. Des trucs sympas là.
Voici un rapide récursive des solutions proposées sur les forums en C#:
C#
Crochets(3);
F#:
Voici une solution qui, contrairement à ma précédente solution, je crois que peut-être raison. Aussi, il est plus efficace.
Exemple:
Version de Python de la première voté réponse.
Voici un autre F# solution, privilégiant l'élégance par rapport à l'efficacité, bien que memoization conduirait probablement à une relativement bien l'exécution de la variante.
Encore une fois, cela ne donne une liste de ces chaînes avec exactement n paires de parenthèses (plutôt qu'au plus n), mais il est facile pour l'envelopper.
F#:
Mise à JOUR: cette réponse est fausse. Mon N=4 manque, par exemple "(())(())". (Voyez-vous pourquoi?) Je vais poster un correct (et plus efficace) de l'algorithme de peu de temps.
(Honte à tous vous les électeurs, pour ne pas attraper moi! 🙂 )
Inefficace, mais court et simple.
(Notez qu'il n'imprime que la "nième" ligne; d'appeler dans une boucle à partir de 1..n pour obtenir le résultat demandé par la question.)
Exemple:
La solution la plus Simple en C++:
De sortie:
Merde - tout le monde me battre pour elle, mais j'ai un bel exemple de travail 🙂
http://www.fiveminuteargument.com/so-727707
La clé est d'identifier les règles, qui sont en fait assez simple:
Common Lisp:
Cela n'a pas l'impression, mais ne produire une liste de listes de toutes les structures possibles. Ma méthode est un peu différente de celle des autres. Il restructure les solutions à
brackets(n - 1)
tels qu'ils deviennentbrackets(n)
. Ma solution n'est pas de queue récursive, mais il peut être fait avec un peu de travail.Code
Voici une solution en C++. L'idée principale que j'utilise c'est que je prend la sortie de la précédente je (où je est le nombre de support de paires), et les aliments qui en tant qu'entrée pour la prochaine je. Ensuite, pour chaque chaîne de caractères en entrée, nous avons mis un support pour une paire à chaque position dans la chaîne. Les nouvelles chaînes sont ajoutées à un ensemble afin d'éliminer les doublons.
Un simple F#/OCaml solution :
(kin, qui est quelque chose comme un acteur modèle linéaire basé sur python, avec des traits. Je n'ai pas rond à la mise en œuvre de @memo mais les travaux ci-dessus sans que l'optimisation)
Haskell:
J'ai essayé de venir avec un élégant liste monade-y de façon à ce:
pourquoi je ne peux pas c'est aussi simple que cela, c'est une idée assez simple
crochets(n) --> '()' + crochets(n-1) 0
'(' + crochets(n-1) + ')' 0
crochets(n-1) + '()'
où 0 est l'opération de concaténation ci-dessus
Groovy version basée sur le markt élégant c# solution ci-dessus. Le contrôle dynamique de d'ouvrir et de fermer (l'information a été répété en sortie et args) ainsi que la suppression d'un couple d'étrangers logique des contrôles.
Prestataire C# version basée sur un retour en arrière récursif de l'algorithme, espérons que cela est utile.
Pas la solution la plus élégante, mais c'était la façon dont je l'ai fait en C++ (Visual Studio 2008). Tirant parti de la STL ensemble afin d'éliminer les doublons, j'ai juste naïvement insérer de nouvelles () paires dans chaque chaîne index dans chaque chaîne de la génération précédente, puis, de manière récursive.
version de ruby:
Un autre inefficace mais élégant réponse =>
Une tentative avec memoization:
De l'appelant -
function(2*brackets, str, 0, 0);
Référence: Permutations de Parenthèses
J'ai été demandé à cette question dans une interview aujourd'hui.
J'ai toujours ignoré cette question dans Les Fissures de Codage parce que je pensais que c'est une question idiote pour une entrevue. L'interviewer n'a pas de partager mon avis cependant.
Ci-dessous est la solution que j'ai pu arriver à l'entrevue. L'interviewer était à la recherche à la plus performante de la méthode qui est déjà donné ci-dessus. Il m'a passé, bien que pour cette solution.
L'espace de la complexité de l'autre plus performant solution est O(1), mais l'un est O(Cn), où Cn est Catalan Nombre.
La complexité du temps de ce code est le même que l'autre à haute performance de la solution, qui est la même que O(Cn).
En C#