Vérifier si deux listes de fusion. Si oui, où?
Cette question peut-être vieux, mais je ne pouvais pas penser à une réponse.
Dire, il y a deux listes de longueurs différentes, la fusion au point; comment savons-nous où le point de fusion est?
Conditions:
- Nous ne connaissons pas la longueur
- Nous devrions analyser chaque liste qu'une seule fois.
- la fusion signifie à partir de ce point, il n'y aura qu'une seule liste.
- est la modification de la liste des admis?
- twitpic.com/m8eqo voir ce pour plus d'idée abt problème, et la modification non autorisés
- À partir de l'image vous pouvez utiliser ce que j'ai posté ci-dessous.
- Je suis assez sûr qu'il ne fonctionne pas sans modification de la liste. (Ou tout simplement de le copier à un autre endroit pour éviter la restriction de l'analyser en une seule fois.)
- Ce qui aurait été le point. Putain enquêteurs! Hehe
- J'ai une proposition intéressante... en supposant que la commune de la queue de la liste est infiniment longue. Comment pouvez-vous trouver le nœud de l'intersection à l'aide de la constante de la mémoire?
- posté ci-dessous une solution sans modification de la liste, les compteurs ou plus de O(N) itérations
- Je vois d'ici les réponses qu'il y est une hypothèse qu'il n'y a pas de boucle dans les listes. Est-ce que vous vouliez dire? Qu'advient-il si il y a une boucle?
- Si il y a une boucle dans une seule liste liée, il serait de la queue. Si deux listes ont fusionné, ils racontaient cette queue et serait d'une longueur infinie. (Ils n'ont pas besoin de partager la tête, comme ils pouvaient entrer dans le cycle sur des nœuds différents.)
- Un exemple en golang O(n^2) et O(n) dans le temps de la complexité, une dernière à l'aide d'un jeu: play.golang.org/p/XpK3D_p-oq
Vous devez vous connecter pour publier un commentaire.
Si
l'algorithme suivant serait la solution.
Tout d'abord, les chiffres. Supposons le premier de la liste est de longueur
a+c
et le second est de longueurb+c
, oùc
est la longueur de la "queue" (après la mergepoint). Nous allons désigner comme suit:Puisque nous ne connaissons pas la longueur, nous allons calculer
x
ety
sans des itérations supplémentaires; vous verrez comment.Ensuite, nous itération de chaque liste et pour renverser la vapeur lors de l'itération! Si les deux itérateurs atteindre le point de fusion dans le même temps, alors nous trouver par simple comparaison. Sinon, un pointeur d'atteindre le point de fusion avant l'autre.
Après cela, lorsque les autres itérateur atteint le point de fusion, il ne procédera pas à la commune de la queue. Au lieu de cela va revenir à l'ancien début de la liste qui avaient atteint la fusion-point avant! Donc, avant qu'il n'atteigne la fin de la modification de la liste (c'est à dire l'ex-début de la liste), il fera
a+b+1
itérations total. Appelons ça de laz+1
.Le pointeur atteint la fusion point d'abord, permet de garder l'itération, jusqu'à atteindre la fin de la liste. Le nombre d'itérations, il doit être calculée et est égale à
x
.Puis, ce pointeur itère arrière et annule les listes de nouveau. Mais maintenant, il ne sera pas revenir au début de la liste qu'il a commencé à partir de! Au lieu de cela, il va aller au début de la liste autres! Le nombre d'itérations, il doit être calculé et égale à
y
.Donc, nous savons que l'un des numéros suivants:
À partir de laquelle nous déterminons que
Qui résout le problème.
La suivante est de loin le plus grand de tout ce que j'ai vu - O(N), pas de compteurs. Je l'ai eu lors d'une interview à un candidat à la S. N. à VisionMap.
Faire un interating pointeur comme ceci: il va de l'avant à chaque fois jusqu'à la fin, et puis saute au début de la face de la liste, et ainsi de suite.
Créez deux de ces, pointant à deux têtes.
L'avance chacun des pointeurs par 1 à chaque fois, jusqu'à ce qu'ils rencontrent. Ce sera le cas après une ou deux passes.
Je continuer à utiliser cette question dans les entretiens - mais pour voir combien de temps il faut quelqu'un pour comprendre pourquoi cette solution fonctionne.
prev
pointeur d'unedoubly linked list
?p2 = p2->next ? p2->next : head1;
et vice versa.a-b-c-x-y-z
etp-q-x-y-z
. chemin de la première pointeura,b,c,x,y,z,p,q,x
, chemin de la deuxième pointeurp,q,x,y,z,a,b,c,x
head1
nihead2
, se trouve aprèsi
houblon dehead1
et *j
houblon dehead2
(dessiner). Maintenir 2 pointeurs,p1 = head1
etp2=head2
. Puis, aprèsn
houblon,p1
sera àhead2
etp2
sera quelque part n'a pas d'importance. Maintenant, aprèsj
houblon,p1
seront à la propriété intellectuelle (pourquoi? parce que * ) etp2
aurait achevén+j
de houblon. La clé est maintenant, pour prouverp2
sera également à la propriété intellectuelle.n-i = m-j
(les nœuds communs entre L1 et L2), oun+j = m+i
. Mettre en commentaire précédent. Nous obtenons,p2
aurait achevém+i
de houblon. Par la recherche de nos étapes, nous le savons, aprèsm
houblonp2
sera àhead1
. Et après les autres " je " étapes dehead1
nous atteindrons IP sûr (pourquoi? parce que l'IP se trouve aprèsi
houblon dehead1
). Donc de prouver, maintenantp2
sera également à la propriété intellectuelle.head1
ouhead2
. Alors soiti
ouj
est égal à zéro. Puis, aprèsn+j
houblon (oum+i
houblon), vous atterrissez dans la même configuration que le premier c'est à direp1
sera àhead1
etp2
sera àhead2
. Cela aurait pour conséquence une boucle infinie. C'est pourquoi, ce n'est pas la réponse.Pavel réponse nécessite une modification de l'listes ainsi que itération chaque liste à deux reprises.
Voici une solution qui seulement nécessite une itération à chaque liste en deux fois (la première fois pour le calcul de leur longueur; si la longueur est donné seulement à itérer une fois).
L'idée est d'ignorer le départ des entrées de la liste la plus longue (de fusion point ne peut pas être là), de sorte que les deux pointeurs sont à égale distance de la fin de la liste. Puis déplacez-les transmet jusqu'à ce qu'ils fusionnent.
C'est asymptotiquement la même (temps linéaire) comme mon autre réponse, mais probablement moins constantes, donc c'est probablement plus rapide. Mais je pense que ma réponse est plus frais.
Bien, si vous savez qu'ils vont fusionner:
Dire que vous commencez avec:
1) Allez par le biais de la première configuration de la liste de chaque côté du pointeur à NULL.
Maintenant, vous avez:
2) Maintenant, allez dans la deuxième liste et attendre jusqu'à ce que vous voyez une NULLE, ce qui est votre point de fusion.
Si vous ne pouvez pas être sûr qu'ils fusionner, vous pouvez utiliser une sentinelle de la valeur pour la valeur du pointeur, mais qui n'est pas aussi élégant.
Si l'on peut itérer les listes exactement deux fois, que je peux fournir la méthode pour déterminer le point de fusion:
Voici une solution, le calcul rapide (itération de chaque liste une fois), mais qui utilise beaucoup de mémoire:
Cela a sans doute viole la "analyser chaque liste qu'une seule fois" état, mais de mettre en place le la tortue et le lièvre de l'algorithme (utilisé pour trouver le point de fusion et la longueur du cycle de cyclique liste) si vous commencez à partir d'Une Liste, et lorsque vous atteignez la valeur NULL à la fin vous prétendez que c'est un pointeur vers le début de la liste B, créant l'apparence d'une reprise cyclique de la liste. L'algorithme ne puis vous dire exactement comment loin en bas de la Liste A de la fusion (la variable 'mu', d'après Wikipedia, description).
Aussi, le "lambda" la valeur vous indique la longueur de la liste B, et si vous le souhaitez, vous pouvez déterminer la longueur de la liste A au cours de l'algorithme (lorsque vous rediriger le lien NUL).
Vous pouvez utiliser un ensemble de Nœuds. Itérer sur une liste et d'ajouter à chaque Nœud de l'ensemble. Puis itérer sur la deuxième liste et pour chaque itération, vérifier si le Nœud existe dans le jeu. Si c'est le cas, vous avez trouvé votre point de fusion 🙂
Peut-être que je suis au-dessus de la simplification, mais simplement de réitérer la plus petite de la liste et utilisez les derniers nœuds
Link
que la fusion point?Alors, où
Data->Link->Link == NULL
est le point de fin, donnantData->Link
que la fusion point (à la fin de la liste).EDIT:
Bon, à partir de l'image que vous avez posté, vous analysez les deux listes, le plus petit d'abord. Avec le plus petit de la liste, vous pouvez maintenir les références au nœud suivant. Maintenant, lorsque vous analysez la deuxième liste vous faire une comparaison sur la référence pour trouver d'où la Référence [i] est la référence à LinkedList[i]->Lien. Cela vous donnera le point de fusion. Le temps d'expliquer avec des photos (superposer les valeurs sur l'image de l'OP).
Vous avez une liste chaînée (références indiquées ci-dessous):
A->B->C->D->E
Vous avez une deuxième liste chaînée:
1->2->
Avec la fusion de la liste, les références vont ensuite comme suit:
1->2->D->E->
Par conséquent, vous carte la première "petite" liste (comme la fusion de la liste, qui est ce que nous comptons a une longueur de 4 et de la liste principale 5)
Boucle à travers la première liste, de maintenir une référence de références.
La liste contient les références suivantes
Pointers { 1, 2, D, E }
.Nous maintenant à la seconde liste:
Sûr, vous maintenez une nouvelle liste de pointeurs, mais ce n'est pas en dehors de la spécification. Cependant, le premier de la liste est analysé exactement une fois, et la seconde liste ne sera pleinement analysé si il n'y a pas de point de fusion. Autrement, il va se terminer plus tôt (à la fusion point).
J'ai testé une fusion de cas sur mon FC9 x86_64, et d'impression de chaque nœud de l'adresse comme indiqué ci-dessous:
Note becase j'avais aligné le nœud de la structure, de sorte que lorsque la fonction malloc() d'un nœud, l'adresse est aligné w/16 octets, consultez les moins de 4 bits.
Le moins de bits sont à 0, c'est à dire, 0x0 ou 000b.
Donc, si vous êtes dans le même cas spécial (aligné adresse de nœud), vous pouvez utiliser ces moins de 4 bits.
Par exemple, lorsque le déplacement dans les deux listes de la tête à la queue, set 1 ou 2 des 4 bits de poids fort de l'adresse de nœud, c'est un drapeau;
Note drapeaux ci-dessus n'affectera pas la véritable adresse de nœud, mais seulement votre ENREGISTRÉS nœud de la valeur du pointeur.
Une fois trouvé quelqu'un avait mis le bit indicateur(s), puis le premier nœud doit être le point de fusion.
lorsque vous avez terminé, vous auriez à restaurer l'adresse de nœud par claire le drapeau bits que vous vous étiez fixé. alors une chose importante est que vous devez être prudent lors de l'itération (par exemple, node = node->next) pour faire propre. rappelez-vous que vous vous étiez fixé drapeau bits, afin de faire de cette façon
Parce que cette proposition permettra de restaurer l'modifié nœud adresses, il pourrait être considéré comme "pas de modification".
cette solution itération de chaque liste qu'une seule fois...pas de modification de la liste nécessaire de trop..si vous pouvez vous plaindre à propos de l'espace..
1) en fait, vous itérer dans la liste 1 et stocker l'adresse de chaque nœud dans un tableau(qui stocke unsigned int valeur)
2) Ensuite vous parcourez la liste 2, et pour chaque nœud de l'adresse ---> de la recherche à travers le tableau que vous trouver un match ou pas...si vous le faites, alors c'est la fusion de nœud
Espère que c'est une solution valable...
Il y a peut être une solution simple mais aura besoin d'un auxiliaire de l'espace. L'idée est de parcourir une liste et de les stocker chaque adresse dans une table de hachage de la carte, maintenant parcourir la liste et le match si l'adresse se trouve dans la table de hachage de la carte ou pas. Chaque liste est parcourue qu'une seule fois. Il n'y a aucune modification à toute la liste. La longueur est encore inconnue. Auxiliaire de l'espace utilisé: O(n) où n est la longueur de la première liste traversé.
Il n'est pas nécessaire de modifier la liste. Il y a une solution à laquelle nous n'avons qu'à traverser chaque liste une fois.
Ici est naïf de solution , Pas de neeed pour parcourir des listes entières.
si votre structuré nœud a trois champs comme
dire que vous avez deux têtes (head1 et head2) pointant vers la tête de deux listes.
Traverse à la fois la liste au même rythme et de mettre le flag =1(consulté le drapeau) pour le nœud ,
Comment à ce sujet:
Si vous êtes seulement autorisé à traverser chaque liste qu'une seule fois, vous pouvez créer un nouveau nœud, traverse le premier de la liste pour chaque point de nœud de ce nouveau nœud, et traverse la deuxième liste pour voir si tout nœud est pointant vers votre nouveau nœud (c'est votre point de fusion). Si la deuxième traversée de ne pas conduire à votre nouveau nœud puis les listes initiales n'avez pas de point de fusion.
Si vous êtes autorisé à traverser les listes plus d'une fois, vous pouvez traverser chaque liste pour trouver notre leurs longueurs, et si elles sont différentes, omettez le "extra" nœuds au début de la liste la plus longue. Puis il suffit de parcourir les deux listes, une étape à la fois et de trouver la première fusion de nœud.
Étapes en Java:
Nous pouvons résoudre efficacement en introduisant de "isVisited" sur le terrain. Traverse de la première liste et définissez "isVisited" valeur "true" pour tous les nœuds jusqu'à la fin. Maintenant, commencer à partir de la deuxième et de rechercher le premier nœud où le drapeau est vrai ,et Boum, de son point de fusion.
Étape 1: trouver la longueur de la liste
Étape 2 : Trouver le diff et déplacer la plus grande liste avec la différence
Étape 3 : Maintenant, les deux liste sera dans un poste similaire.
Étape 4 : parcourir la liste pour trouver le point de fusion
Utiliser une Carte ou un Dictionnaire pour stocker les addressess vs valeur de nœud. si l'adresse alread existe dans la Carte/Dictionnaire alors la valeur de la clé est la réponse.
Je l'ai fait:
Un O(n) la complexité de la solution. Mais, sur la base d'une hypothèse.
hypothèse: les deux nœuds sont d'avoir uniquement des entiers positifs.
logique : faire que tous les entiers de la liste 1 à négative. Puis à pied à travers la liste 2, jusqu'à ce que vous obtenez un entier négatif. Une fois trouvé => le prendre, de modifier le signe de retour à la positif et retour.
C'est un vrai problème! Si nous avons une arborescence de base de données sql. Nous voulons trouver la LCA dans un déclencheur SQL.
De déclenchement de l'environnement nous ne pouvons pas créer une table temporaire, car il sera implicitement commit de la transaction. Nous avons donc à faire en O(1) de mémoire, c'est à dire que nous ne pouvons utiliser la variable.