Compruebe si se fusionan dos listas vinculadas. ¿Si es así, donde?


102

Esta pregunta puede ser antigua, pero no se me ocurrió una respuesta.

Digamos, hay dos listas de diferentes longitudes, que se fusionan en un punto ; ¿Cómo sabemos dónde está el punto de fusión?

Condiciones:

  1. No sabemos la longitud
  2. Debemos analizar cada lista solo una vez.

Ejemplo de dos listas enlazadas fusionadas.


fusionar significa que a partir de ese punto solo habrá una lista.
rplusg

¿Se permite la modificación de la lista?
Artelius

1
Estoy bastante seguro de que no funciona sin modificar la lista. (O simplemente copiarlo en otro lugar para evitar la restricción de analizarlo solo una vez.)
Georg Schölly

2
Podría haber sido el punto. ¡Malditos entrevistadores! Jeje
Kyle Rosendo

1
Tengo una propuesta interesante ... asumiendo que la cola común de la lista es infinitamente larga. ¿Cómo puedes encontrar la intersección de nodos usando memoria constante?
Akusete

Respuestas:


36

Si

  • por "la modificación no está permitida" quería decir "puede cambiar, pero al final deberían restaurarse", y
  • podríamos iterar las listas exactamente dos veces

el siguiente algoritmo sería la solución.

Primero, los números. Suponga que la primera lista es de longitud a+cy la segunda es de longitud b+c, donde ces la longitud de su "cola" común (después del punto de fusión). Denotémoslos de la siguiente manera:

x = a+c
y = b+c

Como no conocemos la longitud, la calcularemos xy ysin iteraciones adicionales; ya verás cómo.

Luego, iteramos cada lista y las invertimos mientras iteramos. Si ambos iteradores alcanzan el punto de fusión al mismo tiempo, lo averiguaremos mediante una mera comparación. De lo contrario, un puntero llegará al punto de fusión antes que el otro.

Después de eso, cuando el otro iterador alcance el punto de fusión, no procederá a la cola común. En su lugar, volverá al comienzo anterior de la lista que había alcanzado el punto de fusión antes. Por lo tanto, antes de que llegue al final de la lista modificada (es decir, el comienzo anterior de la otra lista), a+b+1sumará las iteraciones. Vamos a llamarlo z+1.

El puntero que llegó primero al punto de fusión seguirá iterando hasta que llegue al final de la lista. El número de iteraciones que realizó debe calcularse y es igual a x.

Luego, este puntero se repite e invierte las listas nuevamente. ¡Pero ahora no volverá al principio de la lista desde la que comenzó originalmente! En cambio, irá al principio de la otra lista. El número de iteraciones que realizó debe calcularse y ser igual y.

Entonces conocemos los siguientes números:

x = a+c
y = b+c
z = a+b

De lo que determinamos que

a = (+x-y+z)/2
b = (-x+y+z)/2
c = (+x+y-z)/2

Lo que resuelve el problema.


2
Comentario a los estados de la pregunta ¡No se permite la modificación de la lista!
Skizz

1
Me gusta esta respuesta (muy creativa). El único problema que tengo es que asume que conoce la longitud de ambas listas.
tster

no se puede modificar la lista y no sabemos la longitud; estas son las limitaciones ... de todos modos, gracias por una respuesta creativa.
rplusg

2
@tster, @calvin, la respuesta no asume, necesitamos la longitud. Se puede calcular en línea. Añadiendo explicaciones a mis respuestas.
Sábado el

2
@Forethinker hash de los nodos visitados y / o marcarlos como se ve requiere memoria O (longitud de lista), mientras que muchas soluciones (incluida la mía, por imperfecta y complicada que sea) requieren memoria O (1).
P Shved el

156

El siguiente es, con mucho, el mejor de todos los que he visto: O (N), sin contadores. Lo conseguí durante una entrevista a un candidato SN en VisionMap .

Cree un puntero interactivo como este: avanza cada vez hasta el final, luego salta al principio de la lista opuesta, y así sucesivamente. Crea dos de estos, apuntando a dos cabezas. Avance cada uno de los indicadores en 1 cada vez, hasta que se encuentren. Esto sucederá después de una o dos pasadas.

Todavía utilizo esta pregunta en las entrevistas, pero para ver cuánto tiempo le toma a alguien entender por qué funciona esta solución.


6
eso es simplemente brillante!
Cong Hui

2
Esta es una buena respuesta, pero debe revisar las listas dos veces, lo que viola la condición # 2.
tster

2
Encuentro esta solución bastante elegante, si se garantiza la presencia de un punto de fusión. No funcionará para detectar puntos de fusión, ya que si no hay uno presente, se repetirá infinitamente.
dirección alternativa

4
¡Eso es super brillante! Explicación: tenemos 2 listas: a-b-c-x-y-zy p-q-x-y-z. ruta del primer puntero a,b,c,x,y,z,p,q,x, ruta del segundo punterop,q,x,y,z,a,b,c,x
Nikolai Golub

14
Brillante. Para aquellos que no entendieron, cuente el número de nodos viajados desde head1-> tail1 -> head2 -> punto de intersección y head2 -> tail2-> head1 -> punto de intersección. Ambos serán iguales (Dibuje tipos diferentes de listas enlazadas para verificar esto). La razón es que ambos punteros tienen que recorrer las mismas distancias head1-> IP + head2-> IP antes de alcanzar IP nuevamente. Entonces, para cuando llegue a IP, ambos punteros serán iguales y tendremos el punto de fusión.
adev

91

La respuesta de Pavel requiere la modificación de las listas , así como la iteración de cada lista dos veces.

Aquí hay una solución que solo requiere iterar cada lista dos veces (la primera vez para calcular su longitud; si se proporciona la longitud, solo necesita iterar una vez).

La idea es ignorar las entradas iniciales de la lista más larga (el punto de fusión no puede estar allí), de modo que los dos punteros estén a la misma distancia del final de la lista. Luego muévalos hacia adelante hasta que se fusionen.

lenA = count(listA) //iterates list A
lenB = count(listB) //iterates list B

ptrA = listA
ptrB = listB

//now we adjust either ptrA or ptrB so that they are equally far from the end
while(lenA > lenB):
    ptrA = ptrA->next
    lenA--
while(lenB > lenA):
    prtB = ptrB->next
    lenB--

while(ptrA != NULL):
    if (ptrA == ptrB):
        return ptrA //found merge point
    ptrA = ptrA->next
    ptrB = ptrB->next

Esto es asintóticamente lo mismo (tiempo lineal) que mi otra respuesta, pero probablemente tiene constantes más pequeñas, por lo que probablemente sea más rápido. Pero creo que mi otra respuesta es más genial.


4
Hoy, cuando estábamos bebiendo vodka, le propuse esta pregunta a un amigo mío, y me dio la misma respuesta que la tuya y pidió publicarla en SO. Pero pareces ser el primero. Así que haré un +1 para ti y me gustaría poder hacer otro +1.
P Shved el

2
+1 como este y tampoco necesita ninguna modificación en la lista, también la mayoría de las implementaciones de listas vinculadas generalmente proporcionan longitud
keshav84

3
Tenemos demasiados Pavel. Mi solución no requiere modificar la lista.
Pavel Radzivilovsky

Buena respuesta. Sin embargo, cuál será la complejidad del tiempo para esto. 0 (n + m)? donde n = nodos en la lista 1, m = nodos en la lista 2?
Vihaan Verma

en lugar de mover ambos punteros en ambas listas: podemos ver si el diff> = pequeño de dos caminos, si es así, entonces mover en la lista pequeña por valor pequeño, de lo contrario mover en lista pequeña por valor diff + 1; si diff es 0, el último nodo es la respuesta.
Vishal Anand

30

Bueno, si sabes que se fusionarán:

Digamos que comienzas con:

A-->B-->C
        |
        V
1-->2-->3-->4-->5

1) Revise la primera lista configurando cada puntero siguiente en NULL.

Ahora tu tienes:

A   B   C

1-->2-->3   4   5

2) Ahora revise la segunda lista y espere hasta que vea un NULL, ese es su punto de fusión.

Si no puede estar seguro de que se fusionen, puede usar un valor centinela para el valor del puntero, pero eso no es tan elegante.


3
Sin embargo, destruye la lista en el proceso, para que nunca más se vuelva a usar: P
Kyle Rosendo

@Kyle Rozendo, bueno, mi solución cambia las listas en la forma en que se pueden restaurar después del procesamiento. Pero esta es una demostración más clara del concepto
P Shved

No vi que no se permitiera la modificación de la lista. Lo pensaré, pero no se me viene nada a la mente sin almacenar todos los nodos vistos.
tster

10
¡Vamos, esa es la respuesta correcta! Solo necesitamos ajustar la pregunta :)
P Shved

23
Excelente algoritmo para crear pérdidas de memoria.
Karoly Horvath

14

Si pudiéramos iterar listas exactamente dos veces, entonces puedo proporcionar un método para determinar el punto de fusión:

  • iterar ambas listas y calcular las longitudes A y B
  • calcular la diferencia de longitudes C = | AB |;
  • comience a iterar ambas listas simultáneamente, pero realice pasos C adicionales en la lista que fue mayor
  • estos dos punteros se encontrarán en el punto de fusión

8

Aquí hay una solución, computacionalmente rápida (itera cada lista una vez) pero usa mucha memoria:

for each item in list a
  push pointer to item onto stack_a

for each item in list b
  push pointer to item onto stack_b

while (stack_a top == stack_b top) // where top is the item to be popped next
  pop stack_a
  pop stack_b

// values at the top of each stack are the items prior to the merged item

2
Eso es el equivalente a procesar una lista dos veces.
Georg Schölly

Supongo que, técnicamente, estás haciendo cosas con las listas dos veces, pero es una mejora significativa en la solución de Kyle Rozendo. Ahora, si 'procesar la lista' se define como 'leer el valor del enlace y seguir el puntero', se podría argumentar que procesa la lista una vez: lee cada valor de enlace una vez, lo almacena y luego los compara.
Skizz

Definitivamente va a ser más rápido que el mío, sin duda.
Kyle Rosendo

7

Puede utilizar un conjunto de Nodos. Repita una lista y agregue cada nodo al conjunto. Luego, recorra la segunda lista y, para cada iteración, verifique si el nodo existe en el conjunto. Si es así, ha encontrado su punto de fusión :)


Me temo que (debido a Ω (n) espacio adicional) este es el único enfoque (no es una especie de reconstrucción de la (s) lista (s) y) no analiza una lista más de una vez. Detectar un bucle en la lista es trivial para la primera lista (verifique si el nodo está en el conjunto) - use cualquier método de detección de bucle en la segunda lista para asegurar la terminación. (La pregunta de la entrevista puede haber estado a punto de escuchar cuidadosamente a un planteamiento del problema, y no saltar a usar un martillo por casualidad usted conoce a golpe no es algo bastante un clavo.)
Barbagrís-

6

Podría decirse que esto viola la condición "analizar cada lista solo una vez", pero implementa el algoritmo de la tortuga y la liebre (que se usa para encontrar el punto de fusión y la duración del ciclo de una lista cíclica) para comenzar en la Lista A, y cuando llegue a NULL en el Al final, finge que es un puntero al principio de la lista B, creando así la apariencia de una lista cíclica. A continuación, el algoritmo le dirá exactamente qué tan abajo de la Lista A está la fusión (la variable 'mu' según la descripción de Wikipedia).

Además, el valor "lambda" le indica la longitud de la lista B y, si lo desea, puede calcular la longitud de la lista A durante el algoritmo (cuando redirige el enlace NULL).


Más o menos lo que dije, solo con nombres más elegantes. : P
Kyle Rosendo

De ningún modo. Esta solución es O (n) en operaciones y O (1) en uso de memoria (de hecho, solo requiere dos variables de puntero).
Artelius

Sí, debería haber eliminado mi comentario anterior ya que mi solución cambió un poco. Jeje.
Kyle Rosendo

Pero no veo cómo fue aplicable eso en primer lugar.
Artelius

Tu explicación lo hizo, no el algoritmo en sí. Quizás lo veo de otra manera, pero bueno.
Kyle Rosendo

3

Tal vez estoy simplificando demasiado esto, pero simplemente iterar la lista más pequeña y usar los últimos nodos Linkcomo punto de fusión.

Entonces, ¿dónde Data->Link->Link == NULLestá el punto final, dando Data->Linkcomo punto de fusión (al final de la lista).

EDITAR:

De acuerdo, a partir de la imagen que publicó, analice las dos listas, la más pequeña primero. Con la lista más pequeña puede mantener las referencias al siguiente nodo. Ahora, cuando analice la segunda lista, haga una comparación en la referencia para encontrar donde Reference [i] es la referencia en LinkedList [i] -> Link. Esto le dará el punto de fusión. Es hora de explicar con imágenes (superponer los valores en la imagen del OP).

Tiene una lista vinculada (las referencias se muestran a continuación):

A->B->C->D->E

Tienes una segunda lista vinculada:

1->2->

Con la lista combinada, las referencias serían las siguientes:

1->2->D->E->

Por lo tanto, mapea la primera lista "más pequeña" (ya que la lista combinada, que es lo que estamos contando tiene una longitud de 4 y la lista principal 5)

Recorra la primera lista, mantenga una referencia de referencias.

La lista contendrá las siguientes referencias Pointers { 1, 2, D, E }.

Ahora pasamos por la segunda lista:

-> A - Contains reference in Pointers? No, move on
-> B - Contains reference in Pointers? No, move on
-> C - Contains reference in Pointers? No, move on
-> D - Contains reference in Pointers? Yes, merge point found, break.

Seguro, mantiene una nueva lista de punteros, pero eso no está fuera de la especificación. Sin embargo, la primera lista se analiza exactamente una vez, y la segunda lista solo se analizará completamente si no hay un punto de fusión. De lo contrario, terminará antes (en el punto de fusión).


Bueno, cambia ligeramente de lo que quería decir al principio, pero de lo que parece querer el OP, esto funcionará.
Kyle Rosendo

Ahora está más claro. Pero lineal en el uso de la memoria. No me gusta eso.
Artelius

La pregunta no pedía más, de lo contrario, todo el proceso puede ser multiproceso. Esta sigue siendo una vista simplista de "nivel superior" de la solución, el código se puede implementar de muchas formas. :)
Kyle Rosendo

1
¿Cómo? El subproceso múltiple es una forma de utilizar mejor la potencia de procesamiento, sin reducir la potencia de procesamiento total que requiere un algoritmo. Y decir que el código se puede implementar de muchas formas es solo una excusa.
Artelius

1
Esto realmente dobla el 'analizar cada lista solo una vez' hasta casi el punto de ruptura. Todo lo que está haciendo es copiar una lista y luego comparar la otra lista con la copia.
Skizz

3

Probé un caso de combinación en mi FC9 x86_64 e imprimí cada dirección de nodo como se muestra a continuación:

Head A 0x7fffb2f3c4b0
0x214f010
0x214f030
0x214f050
0x214f070
0x214f090
0x214f0f0
0x214f110
0x214f130
0x214f150
0x214f170


Head B 0x7fffb2f3c4a0
0x214f0b0
0x214f0d0
0x214f0f0
0x214f110
0x214f130
0x214f150
0x214f170

Tenga en cuenta porque había alineado la estructura del nodo, por lo que cuando malloc () un nodo, la dirección está alineada con 16 bytes, vea los 4 bits como mínimo. Los bits mínimos son 0, es decir, 0x0 o 000b. Entonces, si también está en el mismo caso especial (dirección de nodo alineada), puede usar estos 4 bits como mínimo. Por ejemplo, cuando recorra ambas listas de principio a fin, establezca 1 o 2 de los 4 bits de la dirección del nodo visitante, es decir, establezca una bandera;

next_node = node->next;
node = (struct node*)((unsigned long)node | 0x1UL);

Tenga en cuenta que los indicadores anteriores no afectarán la dirección del nodo real, sino solo el valor del puntero del nodo GUARDADO.

Una vez encontrado, alguien había establecido los bits de la bandera, entonces el primer nodo encontrado debería ser el punto de fusión. una vez hecho esto, restauraría la dirección del nodo borrando los bits de bandera que había establecido. mientras que una cosa importante es que debe tener cuidado al iterar (por ejemplo, nodo = nodo-> siguiente) para limpiar. recuerde que ha establecido bits de bandera, así que hágalo de esta manera

real_node = (struct node*)((unsigned long)node) & ~0x1UL);
real_node = real_node->next;
node = real_node;

Debido a que esta propuesta restaurará las direcciones de nodo modificadas, podría considerarse como "sin modificación".


+1, esto es lo que naturalmente me viene a la mente con "iterar solo una vez", ¡no sé por qué esto nunca se votó! Hermosa solución.
jman

3

Puede haber una solución simple pero requerirá un espacio auxiliar. La idea es recorrer una lista y almacenar cada dirección en un mapa hash, ahora recorrer la otra lista y hacer coincidir si la dirección se encuentra en el mapa hash o no. Cada lista se recorre solo una vez. No hay modificaciones en ninguna lista. La longitud aún se desconoce. Espacio auxiliar utilizado: O (n) donde 'n' es la longitud de la primera lista recorrida.


2

esta solución itera cada lista solo una vez ... no se requiere modificación de la lista también ... aunque puede quejarse del espacio ...
1) Básicamente, itera en list1 y almacena la dirección de cada nodo en una matriz (que almacena el valor int sin firmar)
2) Luego itera list2, y para la dirección de cada nodo ---> busca en la matriz que encuentra una coincidencia o no ... si lo hace, entonces este es el nodo de fusión

//pseudocode
//for the first list
p1=list1;
unsigned int addr[];//to store addresses
i=0;
while(p1!=null){
  addr[i]=&p1;
  p1=p1->next;
}
int len=sizeof(addr)/sizeof(int);//calculates length of array addr
//for the second list
p2=list2;
while(p2!=null){
  if(search(addr[],len,&p2)==1)//match found
  {
    //this is the merging node
    return (p2);
  }
  p2=p2->next;
}

int search(addr,len,p2){
  i=0;  
  while(i<len){
    if(addr[i]==p2)
      return 1;
    i++;
  }
 return 0;
} 

Espero que sea una solución válida ...


Esto prácticamente itera una de las listas más de una vez, aunque en forma de matriz en lugar de la lista en sí.
syockit

1

No es necesario modificar ninguna lista. Existe una solución en la que solo tenemos que recorrer cada lista una vez.

  1. Cree dos pilas, digamos stck1 y stck2.
  2. Recorra la primera lista y envíe una copia de cada nodo que recorra en stck1.
  3. Igual que el paso dos, pero esta vez recorra la segunda lista y empuje la copia de nodos en stck2.
  4. Ahora, salga de ambas pilas y verifique si los dos nodos son iguales, si es así, mantenga una referencia a ellos. Si no, entonces los nodos anteriores que eran iguales son en realidad el punto de fusión que estábamos buscando.

1
int FindMergeNode(Node headA, Node headB) {
  Node currentA = headA;
  Node currentB = headB;

  // Do till the two nodes are the same
  while (currentA != currentB) {
    // If you reached the end of one list start at the beginning of the other
    // one currentA
    if (currentA.next == null) {
      currentA = headA;
    } else {
      currentA = currentA.next;
    }
    // currentB
    if (currentB.next == null) {
      currentB = headB;
    } else {
      currentB = currentB.next;
    }
  }
  return currentB.data;
}

En su revisión original, esto acaba de detallar la respuesta más votada (Pavel Radzivilovsky, 2013) .
barba gris

0

Aquí hay una solución ingenua, no es necesario recorrer listas completas.

si su nodo estructurado tiene tres campos como

struct node {
    int data;   
    int flag;  //initially set the flag to zero  for all nodes
    struct node *next;
};

digamos que tiene dos cabezas (head1 y head2) apuntando a la cabeza de dos listas.

Recorre ambas listas al mismo ritmo y coloca la bandera = 1 (bandera visitada) para ese nodo,

  if (node->next->field==1)//possibly longer list will have this opportunity
      //this will be your required node. 

0

Qué tal esto:

  1. Si solo se le permite atravesar cada lista solo una vez, puede crear un nuevo nodo, atravesar la primera lista para que cada nodo apunte a este nuevo nodo y atravesar la segunda lista para ver si algún nodo apunta a su nuevo nodo ( ese es tu punto de fusión). Si el segundo recorrido no conduce a su nuevo nodo, las listas originales no tienen un punto de fusión.

  2. Si se le permite recorrer las listas más de una vez, entonces puede recorrer cada lista para encontrar nuestras longitudes y si son diferentes, omita los nodos "extra" al comienzo de la lista más larga. Luego, simplemente recorra ambas listas paso a paso y encuentre el primer nodo de fusión.


1. no solo modifica sino que destruye la primera lista. 2. se sugiere una y otra vez.
barba gris

0

Pasos en Java:

  1. Crea un mapa.
  2. Comience a atravesar ambas ramas de la lista y coloque todos los nodos de la lista atravesados ​​en el mapa utilizando algo único relacionado con los nodos (por ejemplo, Id del nodo) como clave y coloque los valores como 1 al principio para todos.
  3. Cuando llegue la primera clave duplicada, incremente el valor de esa clave (digamos que ahora su valor se convirtió en 2, que es> 1.
  4. Obtenga la clave donde el valor es mayor que 1 y ese debería ser el nodo donde se fusionan dos listas.

1
¿Qué pasa si tenemos un ciclo en la parte fusionada?
Rohit

Pero para los ciclos de manejo de errores, esto se parece mucho a la respuesta de isyi .
greybeard

0

Podemos resolverlo de manera eficiente introduciendo el campo "isVisited". Recorra la primera lista y establezca el valor "isVisited" en "verdadero" para todos los nodos hasta el final. Ahora comience desde el segundo y encuentre el primer nodo donde la bandera es verdadera y Boom, es su punto de fusión.


0

Paso 1: encuentre la longitud de ambas listas Paso 2: Encuentre la diferencia y mueva la lista más grande con la diferencia Paso 3: Ahora ambas listas estarán en una posición similar. Paso 4: iterar a través de la lista para encontrar el punto de fusión

//Psuedocode
def findmergepoint(list1, list2):
lendiff = list1.length() > list2.length() : list1.length() - list2.length() ? list2.lenght()-list1.lenght()
biggerlist = list1.length() > list2.length() : list1 ? list2  # list with biggest length
smallerlist = list1.length() < list2.length() : list2 ? list1 # list with smallest length


# move the biggest length to the diff position to level both the list at the same position
for i in range(0,lendiff-1):
    biggerlist = biggerlist.next
#Looped only once.  
while ( biggerlist is not None and smallerlist is not None ):
    if biggerlist == smallerlist :
        return biggerlist #point of intersection


return None // No intersection found

(Me gustó más la lista con cada elemento comenzando una línea. Considere usar un corrector ortográfico.)
greybeard

0
int FindMergeNode(Node *headA, Node *headB)
{
    Node *tempB=new Node;
    tempB=headB;
   while(headA->next!=NULL)
       {
       while(tempB->next!=NULL)
           {
           if(tempB==headA)
               return tempB->data;
           tempB=tempB->next;
       }
       headA=headA->next;
       tempB=headB;
   }
    return headA->data;
}

Necesita agregar alguna explicación a su respuesta. Las respuestas de solo código pueden eliminarse.
rghome

0

Utilice Mapa o Diccionario para almacenar la dirección frente al valor del nodo. si la dirección ya existe en el Mapa / Diccionario, entonces el valor de la clave es la respuesta. Hice esto:

int FindMergeNode(Node headA, Node headB) {

Map<Object, Integer> map = new HashMap<Object, Integer>();

while(headA != null || headB != null)
{
    if(headA != null && map.containsKey(headA.next))
    {
        return map.get(headA.next);
    }

    if(headA != null && headA.next != null)
    {
         map.put(headA.next, headA.next.data);
         headA = headA.next;
    }

    if(headB != null && map.containsKey(headB.next))
    {
        return map.get(headB.next);
    }

    if(headB != null && headB.next != null)
    {
        map.put(headB.next, headB.next.data);
        headB = headB.next;
    }
}

return 0;
}

0

Solución de complejidad AO (n). Pero basado en una suposición.

La suposición es: ambos nodos solo tienen números enteros positivos.

lógica: convierte todo el número entero de list1 en negativo. Luego, recorra la lista2 hasta que obtenga un número entero negativo. Una vez encontrado => tómalo, cambia el signo de nuevo a positivo y regresa.

static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {

    SinglyLinkedListNode current = head1; //head1 is give to be not null.

    //mark all head1 nodes as negative
    while(true){
        current.data = -current.data;
        current = current.next;
        if(current==null) break;
    }

    current=head2; //given as not null
    while(true){
        if(current.data<0) return -current.data;
        current = current.next;
    }

}

0

Podemos usar dos punteros y movernos de tal manera que si uno de los punteros es nulo lo apuntamos al encabezado de la otra lista y lo mismo para el otro, de esta manera si las longitudes de la lista son diferentes se encontrarán en la segunda pasada . Si la longitud de list1 es n y list2 es m, su diferencia es d = abs (nm). Cubrirán esta distancia y se encontrarán en el punto de fusión.
Código:

int findMergeNode(SinglyLinkedListNode* head1, SinglyLinkedListNode* head2) {
    SinglyLinkedListNode* start1=head1;
    SinglyLinkedListNode* start2=head2;
    while (start1!=start2){
        start1=start1->next;
        start2=start2->next;
        if (!start1)
        start1=head2;
        if (!start2)
        start2=head1;
    }
    return start1->data;
}

0

Puede agregar los nodos de list1a un hashset y el bucle a través del segundo y si algún nodo de list2ya está presente en el conjunto. Si es así, entonces ese es el nodo de fusión

static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {
    HashSet<SinglyLinkedListNode> set=new HashSet<SinglyLinkedListNode>();
    while(head1!=null)
    {
        set.add(head1);
        head1=head1.next;
    }
    while(head2!=null){
        if(set.contains(head2){
            return head2.data;
        }
    }
    return -1;
}

0

Solución usando javascript

var getIntersectionNode = function(headA, headB) {
    
    if(headA == null || headB == null) return null;
    
    let countA = listCount(headA);
    let countB = listCount(headB);
    
    let diff = 0;
    if(countA > countB) {

        diff = countA - countB;
        for(let i = 0; i < diff; i++) {
            headA = headA.next;
        }
    } else if(countA < countB) {
        diff = countB - countA;
        for(let i = 0; i < diff; i++) {
            headB = headB.next;
        }
    }

    return getIntersectValue(headA, headB);
};

function listCount(head) {
    let count = 0;
    while(head) {
        count++;
        head = head.next;
    }
    return count;
}

function getIntersectValue(headA, headB) {
    while(headA && headB) {
        if(headA === headB) {
            return headA;
        }
        headA = headA.next;
        headB = headB.next;
    }
    return null;
}

0

Si se permite editar la lista vinculada,

  1. Luego, simplemente haga que los siguientes punteros de todos los nodos de la lista 2 sean nulos.
  2. Encuentre el valor de datos del último nodo de la lista 1. Esto le dará el nodo que se cruza en un solo recorrido de ambas listas, sin "lógica de alta fidelidad".
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.