Comment puis-je imprimer tous les possibles combinaisons de lettres un numéro de téléphone peut représenter?
J'ai juste essayé pour ma première interview de programmation et l'une des questions était d'écrire un programme qui, étant donné un 7 chiffres du numéro de téléphone, peut imprimer toutes les combinaisons possibles de lettres que chaque nombre peut représenter.
Une deuxième partie de la question était comme si cela aurait été un 12 chiffres du numéro international? Comment serait-ce l'effet de votre conception.
Je n'ai pas le code que j'ai écrit dans l'interview, mais j'ai eu l'impression qu'il n'était pas heureux avec elle.
Quelle est la meilleure façon de le faire?
- pourriez-vous nous donner un résumé de ce que vous avez pris le problème?
- avez-vous le faire de manière récursive ou itérative? Si votre approche initiale n'était pas récursive, alors il serait probablement plus difficile à généraliser à un nombre quelconque de chiffres (d'où la question qui suit).
- D'abord, je l'ai fait de manière itérative, mais a suggéré que je pourrais le faire de manière récursive ainsi.
- Vérifier ma réponse à l'aide de Java 8: stackoverflow.com/a/54499782/1216775 et de la vidéo:youtube.com/watch?v=3_Kx8ChYOFk pour plus d'explication. Le temps de la complexité serait O(4^n).
Vous devez vous connecter pour publier un commentaire.
En Python, itératif:
ret
est une liste de résultats jusqu'à présent; d'abord, il est rempli avec un seul élément, la chaîne vide. Ensuite, pour chaque caractère dans la chaîne d'entrée, il cherche la liste des lettres qui correspondent de la dict définies dans la partie supérieure. Puis, il remplace la listeret
avec la combinaison du préfixe actuel et possible lettre.itertools.product
qui fait exactement ce que vous avez mis en œuvre.Il est semblable à un question appelé les combinaisons de lettres d'un numéro de téléphone,
voici ma solution.
Cela fonctionne pour un nombre arbitraire de chiffres, tant que le résultat ne dépasse pas la limite de la mémoire.
Je ne suis pas sûr de savoir comment à 12 chiffres des numéros internationaux influent sur la conception.
Edit: numéros Internationaux seront également traitées
En Java en utilisant la récursivité:
List.add
appel de méthode à unprintln
ou autre chose pour éviter ce problème.La solution la plus évidente est une fonction de la carte un chiffre à une liste de clés, puis une fonction qui permettrait de générer les combinaisons possibles:
La première est évidente, la seconde est plus problématique parce que vous avez autour de 3^nombre de combinaisons de chiffres, qui peuvent être d'un très grand nombre.
Une façon de le faire est de regarder à chaque possibilité, pour les chiffres correspondants pour un chiffre dans un nombre (sur la base de 4) et de mettre en œuvre quelque chose de proche d'un compteur (saut à plus de certains cas, car il y a généralement moins de 4 lettres transposable à un chiffre).
La plus évidente des solutions serait de boucles imbriquées ou la récursivité, qui sont à la fois moins élégant, mais à mon avis valable.
Une autre chose pour laquelle il faut prendre soin de est pour éviter les problèmes d'échelle (par exemple en gardant les possibilités de la mémoire, etc.) puisque nous parlons de beaucoup de combinaisons.
P. S. une Autre extension intéressante de la question de la localisation.
En C++(récursive):
Cette fonction peut être appelée avec un 'k' et 'i' qui est égale à zéro.
N'importe qui, qui nécessite plus de l'illustration afin de comprendre la logique, peut se combiner à la récursivité technique avec la sortie suivante:
Numérique des claviers, des textes et des nombres sont placés sur la même touche. Pour l'exemple 2, a “ABC” si nous voulions écrire tout ce qui commence par "A", nous avons besoin de taper la touche 2 une fois. Si nous voulions type "B", appuyez sur la touche 2 deux fois et trois fois pour écrire "C". ci-dessous est l'image d'un tel clavier.
clavier http://d2o58evtke57tz.cloudfront.net/wp-content/uploads/phoneKeyboard.png
Donné un clavier comme indiqué dans le schéma, et d'un n nombre de chiffre, de la liste de tous les mots qui sont possibles en appuyant sur ces chiffres.
Par exemple, si le numéro d'entrée est de 234, mots possibles qui peuvent être formés sont (par ordre Alphabétique):
adg adh adi aeg aeh aei afg afh, l'afi bdg bdh bdi beg beh bei bfg bfh bfi cdg cdh cdi ceg ceh cei cfg cfh fci
Nous allons faire quelques calculs en premier. Combien de mots sont possibles avec sept chiffres avec les chiffres représentant les n lettres? Pour le premier chiffre, nous avons tout au plus quatre choix, et pour chaque choix de la première lettre, nous avons tout au plus quatre choix pour le deuxième chiffre, et ainsi de suite. Il est donc simple de maths, il sera O(4^n). Depuis les touches 0 et 1 n'ont pas d'alphabet, et de nombreux personnages ont 3 personnages, 4^n serait à la limite supérieure du nombre de mots et le minimum de mots.
Maintenant, nous allons faire quelques exemples.
Pour le nombre au-dessus de 234. Voyez-vous de n'importe quel motif? Oui, nous remarquons que le dernier caractère toujours soit G,H ou I et à chaque fois qu'il remet à sa valeur de I à G, le chiffre à gauche de celle-ci est changé.
De la même façon à chaque fois que l'avant-dernière de l'alphabet réinitialise sa valeur, le troisième de la dernière de l'alphabet est modifiée et ainsi de suite. Premier caractère réinitialise une seule fois, lorsque nous avons généré tous les mots. Ceci peut être vu à partir de l'autre extrémité également. C'est-à-dire chaque fois que le caractère à la position i les changements, le caractère à la position i+1 passe par tous les caractères possibles et il crée l'effet d'entraînement jusqu'à nous rejoindre à la fin.
Puisque 0 et 1 n'ont pas de caractères qui leur sont associés. nous devons casser car il n'y aura pas d'itération pour ces chiffres.
Prenons la deuxième approche, comme il sera facile à mettre en œuvre en utilisant la récursivité. Nous allons jusqu'à la fin et revenir un par un. Parfait état pour la récursivité. nous allons chercher la base de cas.
Lorsque nous arrivons au dernier caractère, nous imprimons la parole avec tous les caractères possibles pour le dernier chiffre et le retour. Simple de la base de cas.Lorsque nous arrivons au dernier caractère, nous imprimons la parole avec tous les caractères possibles pour le dernier chiffre et le retour. Simple de la base de cas.
Suivant est C mise en œuvre de l'approche récursive pour l'impression de tous les mots possibles correspondant à un n chiffres du numéro d'entrée. Noter que le nombre d'entrée est représenté comme un tableau pour simplifier le code.
De sortie:
Complexité Temporelle:
Temps de complexité de code ci-dessus est O(4^n) où n est le nombre de chiffres dans le numéro d'entrée.
Références:
http://www.flipkart.com/programming-interviews-exposed-secrets-landing-your-next-job-3rd/p/itmdxghumef3sdjn?pid=9788126539116&affid=sandeepgfg
En JavaScript. Un CustomCounter classe prend soin de l'incrémentation de l'index. Alors juste sortie les différentes combinaisons possibles.
Ce problème est similaire à cette leetcode problème. Voici la réponse que j'ai soumis ce problème à leetcode (vérifier github et vidéo pour l'explication).
De sorte que la première chose dont nous avons besoin est une certaine façon de tenir les mappages d'un chiffre et on peut utiliser une carte pour ce:
La méthode ci-dessus est la préparation de la carte et de la méthode suivante je voudrais utiliser est de fournir à la cartographie, à condition chiffres:
Ce problème peut être résolu à l'aide de revenir en arrière et un recul de la solution a généralement une structure où la signature de la méthode contiendra: conteneur de résultat, temp résultats, la source d'origine avec index etc. Si la méthode que la structure pourrait être de la forme:
Et maintenant le corps de la méthode peut être rempli aussi (résultat sera conservé dans une liste, la température dans le générateur de chaîne, etc.)
Et, enfin, la méthode peut être invoquée comme:
Maintenant le max mappé caractères pour un chiffre peut-être 4 (par exemple, 9 wxyz) et les retours en arrière implique une recherche exhaustive pour explorer tous les arrangements possibles (espace d'état de l'arbre) donc pour un chiffre de taille
n
nous allons avoir4x4x4....n times
c'est à dire la complexité seraitO(4^n)
.Utiliser une liste L où L[i] = les symboles que les chiffres que je peux représenter.
L[1] = @,.,! (pour exemple)
L[2] = a,b,c
Etc.
Ensuite, vous pouvez faire quelque chose comme ceci (pseudo-C):
En supposant que chaque liste contient 3 personnages, nous avons 3^7 possibilités de 7 chiffres et 3^12 pour 12, ce qui n'est pas beaucoup. Si vous avez besoin de toutes les combinaisons, je ne vois pas beaucoup mieux. Vous pouvez éviter la récursivité et autres joyeusetés, mais vous n'allez pas pour obtenir quelque chose de beaucoup plus rapide que ce n'importe quoi.
Vous trouvez la source (Scala) ici et un travail applet ici.
Depuis 0 et 1 ne sont pas associés à des caractères, ils construisent naturel des points d'arrêt dans les nombres. Mais ils ne surviennent pas dans chaque numéro (à l'exception de 0 au début). Plus de tels chiffres +49567892345 de 9 chiffres commençant, peut conduire à OutOfMemoryErrors. Il serait donc préférable de diviser un nombre dans des groupes comme
de voir, si vous pouvez faire sens à partir de la plus courte des parties. J'ai écrit un tel programme, et testé certains nombres de mes amis, mais trouve rarement des combinaisons de mots plus courts, ce qui peut être vérifié dans le dictionnaire pour la correspondance, pour ne pas mentionner unique, les mots longs.
Donc, ma décision a été de seulement de faciliter la recherche,, pas d'automatisation complète, par l'affichage de combinaisons possibles, en encourageant le fractionnement du nombre par la main, peut-être plusieurs fois.
J'ai donc trouvé +-RAD JUNG (+-vélo garçon).
Si vous acceptez les fautes d'orthographe, les abréviations, les mots étrangers, les numéros que des mots, des nombres en mots, et les noms, vos chances de trouver une solution est beaucoup mieux, que sans bidouiller.
sont des choses qu'un humain peut observer à faire un algorithme de trouver de telles choses, c'est plutôt dur.
Un Python solution est très économique, et parce qu'il utilise des générateurs est efficace en termes d'utilisation de la mémoire.
Évidemment
itertools.product
est de résoudre le problème pour vous. Mais l'écriture de soi-même n'est pas difficile. Voici une solution en aller, ce qui est prudent de les ré-utiliser le tableauresult
pour générer toutes les solutions, et d'une fermeturef
pour capturer le générés les mots. Combinés, ces donner O(log n) l'utilisation de la mémoire à l'intérieur deproduct
.C'est le C# port de cette réponse.
Code
Tests Unitaires
Cette version en C# est relativement efficace, et cela fonctionne pour les non-ouest de chiffres (comme les "۱۲۳۴۵۶۷" par exemple).
Oracle SQL: Utilisable avec n'importe quel numéro de téléphone de longueur et peut facilement prendre en charge la localisation.
Ici est celui de la douleur C. celui-ci est likley pas efficet (en fait, je ne pense pas que c'est à tous). Mais il y a quelques intresting aspects.
Ce qui est agréable, c'est qu'il n'y a pas vraiment de limite à la taille de la chaîne (pas de limite de caractères) Cela vous permet de générer de plus en plus longues chaînes si besoin est juste en attendant.
Je suis plutôt un débutant, donc s'il vous plaît corrigez-moi où je me trompe.
Première chose à faire est de regarder dans l'espace & le temps de la complexité. Qui est vraiment mauvais depuis qu'il est factoriel
donc, pour factoriel(7) = 5040 tout algorithme récursif ferait. Mais pour la factorielle(12) ~= 4 * 10^8 ce qui peut provoquer un débordement de pile dans la solution récursive.
Donc je ne voudrais pas tenter un algorithme récursif. Le bouclage de la solution est très simple à l'aide de la "Prochaine Permutation".
Je voudrais donc créer et tableau {0, 1, 2, 3, 4, 5} et de générer toutes les permutations et lors de l'impression de les remplacer avec des caractères respectifs, par exemple. 0=A, 5=F
Prochaine Perm algorithme fonctionne comme suit. par exemple Donné 1,3,5,4 prochaine permutation est 1,4,3,5
Les étapes nécessaires pour trouver la prochaine perm.
De droite à gauche, trouver de premier ordre décroissant du nombre. par exemple 3
De gauche à droite, trouver plus petit nombre plus grand que 3, par exemple. 4
Swap de ces numéros à l'inverse du sous-ensemble. 1,4,5,3 inverse sous-ensemble 1,4,3,5
À l'aide de la Prochaine permutation ( ou rotation) vous générez un sous-ensemble spécifique de permutations, dites que vous voulez montrer à 1000 permutations à partir d'un numéro de téléphone particulier. Cela peut vous éviter d'avoir tous les numéros en mémoire. Si je stocker des nombres comme des entiers de 4 octets, 10^9 octets = 1 GO !.
Voici le code de travail pour le même..
son un la récursivité sur chaque étape de vérification de la possibilité pour chacun des combinaisons sur la présence des mêmes chiffres dans une série....Je ne suis pas sûr si il y a une meilleure solution, alors cette complexité point de vue.....
S'il vous plaît laissez-moi savoir pour tous les problèmes....
C'est un algorithme récursif en C++11.
J'ai réécrit la dernière réponse à cette (visées ci-dessus) , de C à Java. J'ai aussi inclus le support pour les 0 et 1 (0 et 1) parce que les nombres tels que 555-5055 ne fonctionnaient pas du tout avec le code ci-dessus.
C'est ici. Certains commentaires sont conservés.
Une option en Objective-C:
Je l'ai essayé en ruby, et est venu avec une façon différente de faire, ce n'est probablement pas efficace, comme le temps et espace O(?) à ce point, mais je l'aime parce qu'il utilise Ruby builtin Tableau.produit de la méthode. Qu'en pensez-vous?
EDIT: je vois une solution très similaire en Python ci-dessus, mais je ne l'avais pas vu quand j'ai ajouté ma réponse
Une R solution à l'aide de boucles imbriquées:
J'ai posté un autre, plus bizarre R solution à l'aide de plus de boucles et d'échantillonnage sur mon blog.
Cette approche utilise R et est basé sur les convertissant d'abord le dictionnaire correspondant à son chiffre de la représentation, puis en utilisant cela comme une look-up.
La conversion ne prend que 1 seconde sur ma machine (conversion à partir de la maternelle Unix dictionnaire d'environ 100 000 mots), et l'aspect typique-ups jusqu'à 100 différents chiffres des entrées de prendre un total de .1 secondes:
Scala solution:
En supposant que chaque chiffre cartes à plus de 4 caractères, le nombre d'appels récursifs
T
satisfaire l'inégalitéT(n) <= 4T(n-1)
, qui est de l'ordre4^n
.J'ai mis en place un cache qui a contribué à réduire le nombre de récurrences. Cette cache d'éviter d'analyse des lettres qu'il avait déjà fait pour la précédente combinaisons. Pour un cas, il allait pour 120k de boucles, d'après le cache de mise en œuvre, il a obtenu réduit à 40k.
Au cours d'une entrevue d'emploi, j'ai reçu cette question de la création d'un tableau et l'impression de tous les possibles combinaisons de lettres d'un numéro de téléphone. Au cours de l'entrevue, j'ai reçu un murmure de mon interviewer au sujet de la récursivité et comment il ne peut pas être fait à l'aide de boucles. Très naturelle pour moi de recevoir des commentaires d'un autre programmeur, j'ai fait confiance à ses conseils au lieu de ma propre scolarité et procédé à écrire un sloppy la récursivité mess. Ça ne va pas si bien. Avant de recevoir de l'entrée, que je n'avais jamais reçu ce problème avant, mon cerveau était en train de calculer le sous-jacent reproductibles formule mathématique. Les chuchotements sous mon souffle, "ne peut pas il suffit de multiplier par trois, certains d'entre eux sont quatre" mon esprit a commencé la compétition à l'encontre d'un court horloge de penser à une réponse tout en commençant à écrire un autre. Il n'était pas jusqu'à la fin de la semaine, j'ai reçu mon appel pour me dire que le triste nouvelle. C'était plus tard dans la nuit, j'ai décidé de voir si c'est vraiment un problème de récursivité. S'avère pour moi il ne l'est pas.
Ma solution ci-dessous est codé en PHP, est non récursif, fonctionne avec n'importe quelle longueur de l'entrée et je l'ai même inclus quelques commentaires pour aider à décrire ce que mes noms de variables. Sa ma officiel et immuable réponse définitive à cette question. J'espère que cela aide quelqu'un d'autre dans l'avenir, n'hésitez pas à le traduire dans d'autres langues.
M'méthode consiste à calculer le nombre total de combinaisons et de la création d'un tampon assez grand pour contenir tous les octets. La longueur de mon tampon est de la même longueur que vous vous attendez à recevoir d'un algorithme récursif. Je fais un tableau qui contient les groupes de lettres qui représentent chaque numéro. Ma méthode fonctionne principalement parce que votre combo total sera toujours divisible par le nombre de lettres dans le groupe actuel. Si vous pouvez imaginer dans votre tête une liste verticale de la sortie de cet algorithme, ou voir la liste à la verticale, par opposition à l'horizontale avec une liste écrite des combinaisons, mon algorithme va commencer à faire sens. Cet algorithme nous permet de parcourir chaque octet verticalement de haut en bas en partant de la gauche, au lieu d'horizontalement de gauche à droite, et de remplir chaque octet individuellement, sans exiger de la récursivité. J'utilise le tampon comme si son un tableau d'octets pour gagner du temps et de l'énergie.
NON-RÉCURSIF ET ITÉRATIF PHP
NON-RÉCURSIVE, NON ITÉRATIF, PAS DE TAMPON, FIL AMICAL, LES MATHÉMATIQUES SEULEMENT + NON-RÉCURSIF ET ITÉRATIF PHP OBJET À L'AIDE DE MULTI-BASE BIG ENDIAN
Alors que je travaillais sur la nouvelle maison, l'autre jour, j'ai eu une prise de conscience que je pouvais utiliser les mathématiques à partir de ma première fonction couplé avec mes connaissances de base pour traiter tous les possibles combinaisons de lettres de mon entrée comme un multi-dimensionnelle nombre.
Mon objet fournit les fonctions nécessaires pour stocker une combinaison préférée dans une base de données, convertir les lettres et les chiffres, si c'était nécessaire, choisir une combinaison de n'importe où dans la combinaison de l'espace à l'aide d'une combinaison préférée ou octet et il joue très bien avec le multi-threading.
Cela étant dit, à l'aide de mon objet, je peux fournir une deuxième réponse qui utilise la base, pas de tampon, pas d'itérations et surtout pas de récursivité.