Lista enlazada DO(2)

Tabla de contenido

1. Combine las dos listas vinculadas ordenadas en una nueva lista vinculada ordenada y devuélvala. La nueva lista enlazada se forma empalmando todos los nodos de las dos listas enlazadas dadas

2. Escriba código para dividir la lista enlazada en dos partes en función del valor dado x, y todos los nodos menores que x se organizan antes de los nodos mayores o iguales a x

3. La estructura palíndromo de la lista enlazada

4. Ingrese dos listas enlazadas y encuentre su primer nodo común

5. Dada una lista enlazada, determine si hay un anillo en la lista enlazada

6. Dada una lista enlazada, devolver el primer nodo de la lista enlazada empezando a entrar en el anillo. Devuelve NULL si la lista enlazada es acíclica

7. Dada una lista enlazada, cada nodo contiene un puntero aleatorio adicional, que puede apuntar a cualquier nodo de la lista enlazada o a un nodo vacío. Solicitud para devolver una copia profunda de esta lista vinculada


¡No te acuestes, sal a brillar!


1.  Combine dos listas vinculadas ordenadas en una nueva lista vinculada ordenada y regrese. La nueva lista enlazada se forma empalmando todos los nodos de las dos listas enlazadas dadas

https://leetcode.cn/problems/merge-two-sorted-lists/

El código 1 muestra : (sin encabezado)

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    if (list1 == NULL)
    {
        return list2;
    }
    if (list2 == NULL)
    {
        return list1;
    }
    struct ListNode* head = NULL;
    struct ListNode* tail = NULL;
    while (list1 && list2)
    {
        struct ListNode* next1 = list1->next;
        struct ListNode* next2 = list2->next;
        if ((list1->val) < (list2->val))
        {
            if (tail == NULL)
            {
                head = list1;
                tail = list1;
            }
            else
            {
                tail->next = list1;
                tail = list1;
            } 
            list1 = next1;
        }
        else
        {
            if (tail == NULL)
            {
                head = list2;
                tail = list2;
            }
            else
            {
                tail->next = list2;
                tail = list2;
            } 
            list2 = next2;
        }
    }

    if (list1 != NULL)
    {
        tail->next = list1;
       
    }

    if (list2 != NULL)
    {
        tail->next = list2;
    }
    return head;
}

Idea : cada vez tome un pequeño nodo e insértelo en un nuevo nodo

Nota : Tenga cuidado cuando uno de ellos esté vacío.

Lista de enlaces simples con encabezado: encabezado->siguiente se refiere a la dirección del primer nodo (principal, equivalente a un nodo adicional al principio, pero el valor en el nodo es incierto y el siguiente apunta al siguiente nodo); -lista enlazada: cabeza Se refiere a la dirección del primer nodo; la pregunta OJ no toma la delantera por defecto

El código 2 muestra : (tomar la iniciativa)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));//创建一个头
    struct ListNode* tail = head;
    head->next = NULL;//就是含有值的节点的第一个
    while (list1 && list2)
    {
        struct ListNode* next1 = list1->next;
        struct ListNode* next2 = list2->next;
        if ((list1->val) < (list2->val))
        {
            tail->next = list1;
            tail = list1;
            list1 = next1;
        }
        else
        {
            tail->next = list2;
            tail = list2;
            list2 = next2;
        }
    }

    if (list1 != NULL)
    {
        tail->next = list1;
       
    }
    if (list2 != NULL)
    {
        tail->next = list2;
    }
    struct ListNode* list = head->next;
    free(head);
    return list;
}

Idea : cada vez tome un pequeño nodo e insértelo en un nuevo nodo

Nota : Al final se debe liberar una dirección de malloc.

2. Escriba código para dividir la lista enlazada en dos partes en función del valor x dado, y todos los nodos menores que x se organizan antes de los nodos mayores o iguales que x

https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8&&tqId=11004&rp=2&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking

Visualización de código :

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        struct ListNode* LessHead = (struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode* LessTail = LessHead;
        struct ListNode* GreaterHead = (struct ListNode*)malloc(sizeof(struct ListNode));
        struct ListNode* GreaterTail = GreaterHead;
        struct ListNode* cur = pHead;
        while (cur != NULL)
        {
            if (cur->val < x)
            {
                LessTail->next = cur;
                LessTail = cur;
            }
            else
            {
                GreaterTail->next = cur;
                GreaterTail = cur;
            }
            cur = cur->next;
        }
        GreaterTail->next = NULL;
        LessTail->next = GreaterHead->next;
        struct ListNode* list = LessHead->next;
        free(LessHead);
        free(GreaterHead);
        return list;


    }
};

Idea : inserte menos de x en una lista enlazada, inserte mayor o igual que x en una lista enlazada, fusione la lista enlazada 1 y la lista enlazada 2 (utilice la primera)

Nota : el último elemento de la lista enlazada 2 debe apuntar a NULL. Si no apunta a NULL, puede causar un bucle infinito [para las preguntas de la lista enlazada, preste atención a la cabeza y la cola]

3.  La estructura palíndromo de la lista enlazada

https://www.nowcoder.com/practice/d281619e4b3e4a60a2cc66ea32855bfa?tpId=49&&tqId=29370&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking

Visualización de código :
 

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode* cur = head;
    struct ListNode* prev = NULL;
    while(cur)
    {
        struct ListNode* next = cur->next;
        cur ->next = prev;
        prev = cur;
        cur = next;
    }
    return prev;
}

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while (fast && (fast ->next))
    {
        slow = slow ->next;
        fast = fast->next->next;
    }
    return slow;
}

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
        struct ListNode* mid = middleNode(A);
        struct ListNode* rHead = reverseList(mid);
        while (A && rHead)
        {
            if (A->val == rHead->val)
            {
                A = A->next;
                rHead = rHead->next;
            }
            else 
            {
                return false;
            }
        }
        return true;
    }
};

Idea : primero encuentre la dirección del medio de la lista vinculada (número impar) o la segunda dirección del medio (número par) como el encabezado de la segunda lista vinculada, luego invierta la segunda lista vinculada, y luego la lista vinculada original y la segunda vinculada lista Comparar. (Cuando una de las listas enlazadas originales y la segunda lista enlazada están vacías, puede saltar fuera del bucle, lo que indica que es una lista enlazada palíndromo

4.  Ingrese dos listas enlazadas y encuentre su primer nodo común

https://leetcode.cn/problems/intersection-of-two-linked-lists/description/

Visualización de código : (idea 2)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    //判断是否相交
    struct ListNode* tailA = headA;
    struct ListNode* tailB = headB;
    int lenA = 1;
    int lenB = 1;
    while (tailA->next != NULL)
    {
        tailA = tailA->next;
        lenA++;
    }
    while (tailB->next != NULL)
    {
        tailB = tailB->next;
        lenB++;
    }
    if (tailA != tailB)
    {
        return NULL;
    }
    //找到节点
    int gap = abs(lenA - lenB);
    //想法值得学习,大小
    struct ListNode* shortList = headA;
    struct ListNode* longList = headB;
    if (lenA > lenB)
    {
        shortList = headB;
        longList = headA;
    }
    while(gap--)
    {
        longList = longList->next;
    }
    while (longList && shortList)
    {
        if (longList == shortList)
        {
            return longList;
        }
        longList = longList->next;
        shortList = shortList->next;
    }
    return NULL;
}

Idea 1 : Compare cada nodo de la lista enlazada A con la lista enlazada B. Si hay igualdad, es la intersección, y el primer igual es el punto de intersección.

(Juzgue si es una intersección y cuántos puntos de intersección) Complejidad de tiempo: O(M*N)

Idea 2 : cuando las direcciones de los nodos de la cola son las mismas, es una intersección. (a juzgar si es una intersección)

Encuentre la longitud de las dos listas vinculadas, y luego recorra primero la diferencia entre las dos listas vinculadas si la lista vinculada es más larga, y luego recorra las dos listas vinculadas juntas. Cuando la dirección es la misma, la posición es el nodo (qué es el punto de intersección) Complejidad temporal: O(M+ N)

Nota : (1) La dirección es la misma, no el valor es igual (el valor no es necesariamente igual al nodo)

(2) Lo que el compilador ejecuta es un error gramatical, y el compilador no puede verificar la lógica de ejecución, por lo que se debe agregar return NULL al final (porque hay un if arriba y luego devuelve un valor, el compilador pensará que cuando la condición si no se cumple, no hay valor de retorno);

5.  Dada una lista enlazada, determine si hay un anillo en la lista enlazada

https://leetcode.cn/problems/linked-list-cycle/submissions/

Visualización de código :

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) 
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while (fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow)
        {
            return true;
        }
    }
    return false;
}

Idea : [puntero rápido y lento] lento da un paso a la vez, rápido da dos pasos a la vez, cuando lento entra en el anillo, el modo de recuperación se activa y, finalmente, rápido alcanza a lento; sin anillo fast->next o fast será NULL, con un anillo No será NULL;

Nota : Al principio, rápido es igual a lento, así que en el ciclo, asigne primero, luego compare

 (1) Lento da un paso a la vez, rápido da dos pasos a la vez, y podrá ponerse al día.

Cuando lento está a la mitad, rápido comienza a entrar en el ring. En este momento, la distancia entre los dos es N, y después de cada vez, la distancia disminuirá en 1, por lo que definitivamente podrán alcanzarlos. [La distancia es 0, ponte al día]

(2) Lento da un paso a la vez, rápido da tres pasos a la vez y es posible que no pueda ponerse al día.

Cuando lento va 1/3, rápido comienza a entrar en el ring. En este momento, la distancia entre los dos es N. Después de cada tiempo, la distancia se reducirá en 2. Si la distancia es un número impar, se perderá. [Los números pares pueden alcanzar]. En este momento, el la distancia es el número de anillo -1 [Los números pares se ponen al día y los números impares se ponen al día] Nunca se pueden alcanzar], por lo que es posible que no se pueda alcanzar.

6.  Dada una lista enlazada, devolver el primer nodo de la lista enlazada empezando a entrar en el anillo.  Devuelve NULL si la lista enlazada es acíclica

https://leetcode.cn/problems/linked-list-cycle-ii/description/

Visualización de código : (idea 1)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) 
{
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while (fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        if (fast == slow)
        {
            struct ListNode* meet = slow;
            while (head != meet)
            {
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}

Idea 1 : Suponga que la distancia antes de entrar al anillo es L; el lento viaja x distancia después de entrar al anillo antes de que los dos se encuentren; la distancia entre los dos después de entrar al anillo es N; la longitud del anillo es C [rápido y lento puntero] lento camina una vez Un paso, rápido da dos pasos a la vez, rápido es el doble de rápido que lento [lento nunca caminará en círculo y será alcanzado por rápido, pero será alcanzado por rápido sin caminar en círculo, porque cuando lento entra al anillo, los dos La distancia es N, y N debe ser menor que el número de anillos, por lo que cuando los dos se encuentran, lento no debe haber completado un círculo, por lo que la distancia recorrida por lento es la distancia antes de entrar al anillo + la distancia antes de que los dos se encuentren y después de entrar al ring x es L+x; la distancia recorrida por rápido es nC+L+x; n*C+L+x=2(L+x),----n *C=L+x; n es un número desconocido]【lento Después de entrar al ring, es imposible que el rápido complete un círculo] n*C=L+x: Se puede probar que uno camina desde la lista de entrada, y el otro camina desde el nodo donde se encuentran, y lento y rápido se encuentran en la entrada del anillo.

Idea 2 : Convertir para encontrar el punto de intersección de la lista enlazada. [Desconectarse del punto de encuentro] encontrarse como la cola, encontrarse->siguiente como la cabeza, se da la cabeza, encontrar el punto de intersección.

7.  Dada una lista enlazada, cada nodo contiene un puntero aleatorio adicional, que puede apuntar a cualquier nodo de la lista enlazada o a un nodo vacío. Solicitud para devolver una copia profunda de esta lista vinculada

https://leetcode.cn/problems/copy-list-with-random-pointer/description/

Visualización de código :

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head)
{
	struct Node* cur = head;
    //拷贝节点链接
    while (cur!= NULL)
    {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;
        copy->next = cur->next;
        cur->next = copy;
        cur = cur->next->next;
    }
    //random
    cur = head;
    while (cur != NULL)
    {
        if (cur->random == NULL)
        {
            cur->next->random = NULL;
        }
        else
        {
            cur->next->random = cur->random->next;
        }
        cur = cur->next->next;
    }
    //摘下来、链接
    struct Node* copyHead = NULL;
    struct Node* copyTail = NULL;
    cur = head;
    while (cur != NULL)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;
        if (copyHead == NULL)
        {
            copyHead  = copyTail = copy;
        }
        else
        {
            copyTail->next = copy;
            copyTail = copy;
        }
        cur = next;
    }
    return copyHead;

}

Idea : copie cada nodo y conéctelo al nodo original, vincule el aleatorio del nodo copiado, y el nuevo aleatorio está al lado del aleatorio anterior. Finalmente, desatar los nodos copiados y vincularlos. [El índice comienza desde 0]


Lista enlazada otras preguntas

Leetcode: https://leetcode.cn/tag/linked-list/problemset/

Niuke.com: https://www.nowcoder.com/exam/oj

Supongo que te gusta

Origin blog.csdn.net/m0_57388581/article/details/131501329
Recomendado
Clasificación