Cepillado diario de LeetCode---Ejercicios de lista enlazada individual de rasgado manual (2)

contenido

1. Estructura palindrómica de lista enlazada

2. Lista enlazada de intersección

3. Copie la lista enlazada con punteros aleatorios


1. Estructura palindrómica de lista enlazada

  • Enlace directo:

Estructura palindrómica de lista enlazada

  • tema:

  •  Ideas:

Encuentre el nodo intermedio y luego inviértalo. Este método es muy inteligente. Los dos contenidos de encontrar el nodo intermedio y la inversión se han explicado en detalle en la publicación de blog anterior. El nodo y el nuevo nodo principal después de la inversión, juzgue si los valores ​​son iguales, si son iguales después del recorrido, devuelve verdadero, de lo contrario, falso.

  •  el código se muestra a continuación:
class PalindromeList {
public:
//第一步:找到中间节点
    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;
    }
//第二部:逆置从中间节点开始往后的数据,并返回新的头节点
    struct ListNode* reverseList(struct ListNode* head) {
        if (head == NULL)
        {
            return NULL;
        }
        struct ListNode* n1 = head;
        struct ListNode* n2 = head->next;
        struct ListNode* n3 = NULL;
        while (n1)
        {
            n1->next = n3;
            n3 = n1;
            n1 = n2;
            if (n2)
            {
                n2 = n2->next;
            }
        }
        return n3;
    }

    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;
    }
};

2. Lista enlazada de intersección

  • Enlace directo:

Lista enlazada de intersección

  • tema:

  • Ideas: 

Método 1: Cada elemento de la lista enlazada A se compara a su vez con la lista enlazada B. Si son iguales, es la intersección, y el primer igual es la intersección.

La complejidad temporal de este método es O(M*N). La ventaja de este método es que los nodos que se cruzan se obtienen directamente después de juzgar si se cruzan o no. Nota: no puede comparar los valores al comparar, debe tomar la dirección Comparar. La desventaja de este método es que la eficiencia es relativamente baja y se puede mejorar.

Método 2: recorrer la lista enlazada original + punteros rápidos y lentos

Primero determine si dos listas enlazadas se cruzan

Recorra las dos listas enlazadas hasta el final por turnos para ver si las direcciones de los dos nodos de la cola son iguales. Si son iguales, deben intersecarse. La complejidad temporal en este momento es O(M+N), que está mucho más optimizada que el primer método.

encontrar la primera intersección

Después de ejecutar el paso anterior, sabemos que las listas enlazadas se cruzan, entonces necesitamos preguntar por el punto de intersección.Primero, encuentre las longitudes La y Lb de las dos listas enlazadas. A continuación, defina dos punteros para que apunten a los encabezados de las dos listas vinculadas respectivamente, deje que el puntero de la lista vinculada con la longitud más larga vaya primero | La-Lb | paso, y luego deje que los dos punteros de la lista vinculada vayan juntos. encontrado, luego deténgase, en este momento Encuentre la intersección. La complejidad temporal de este caso también es O(M+N).

  • el código se muestra a continuación:
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) {
    int lenA = 0;
    int lenB = 0;
    struct ListNode* cur1 = headA;
    struct ListNode* cur2 = headB;
    //1、判断是否相交
    while (cur1->next)
    {
        cur1 = cur1->next;
        lenA++;
    }
    while (cur2->next)
    {
        cur2 = cur2->next;
        lenB++;
    }
    //若相交,进入if判断
    if (cur1 == cur2)
    {
        struct ListNode* shortList = headA, * longList = headB;
        if (lenA > lenB)
        {
            longList = headA;
            shortList = headB;
        }
        int num = abs(lenA - lenB);
        //让长的链表先走差距步
        while (num--)
        {
            longList = longList->next;
        }
        while (shortList && longList)
        {
            if (shortList == longList)
            {
                return shortList;
            }
            //此时两链表一起走
            else
            {
                shortList = shortList->next;
                longList = longList->next;
            }

        }
    }
    //若不相交,则直接返回空
    return NULL;
}

3. Copie la lista enlazada con punteros aleatorios

  • Enlace directo:

Copiar lista enlazada con puntero aleatorio

  • tema:

  •  Ideas:

Método 1: copia directa (malloc) + encontrar distancia relativa

Defina un puntero cur para que apunte al primer elemento de la lista enlazada original, cur para que apunte al primer valor de 7, y luego malloc saque un 7, cur retroceda, continúe malloc, y luego inserte la cola, para atravesar . La nueva lista enlazada se copia. La clave es cómo lidiar con el puntero aleatorio de la nueva lista enlazada. Aquí, podemos usar el método de encontrar distancias relativas para encontrar el número de puntos aleatorios de la lista enlazada original, y luego el nueva lista enlazada corresponde al número de puntos. Pero este método es demasiado complicado y la complejidad del tiempo llega a O(N^2). No muy recomendable

Ley dos:

Primero, vincule el nodo de copia detrás del nodo original

struct Node* cur = head;
//1、拷贝节点链接在原节点后面
while (cur)
{
    struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
    copy->val = cur->val;
    copy->next = cur->next;
    cur->next = copy;
    cur = cur->next->next;
}

A continuación, el azar del nodo de copia del enlace está detrás del azar del nodo original.

Por ejemplo, si copiamos el número 13, el azar del 13 copiado es el siguiente del azar del 13 original. Porque en la lista enlazada original, el aleatorio de 13 apunta a 7, y ahora quiero que el aleatorio de 13 copiado apunte a 7 copiado. En la lista enlazada original, el siguiente de 7 apunta al 7 copiado. En resumen, el azar del 13 copiado es el siguiente del azar del 13 original. Y así.

//2、更新拷贝节点的random
cur = head;
while (cur)
{
    struct Node* copy = cur->next;
    if (cur->random == NULL)
    {
        copy->random = NULL;
    }
    else
    {
        copy->random = cur->random->next;
    }
    cur = cur->next->next;
}

 Finalmente, restaure la lista vinculada original y vincule la lista vinculada copiada.

//3、拷贝节点剪下来,链接到一起
cur = head;
struct Node* copyTail = NULL;
struct Node* copyHead = NULL;
while (cur)
{
    struct Node* copy = cur->next;
    struct Node* next = copy->next;
    cur->next = next;
    if (copyTail == NULL)
    {
        copyHead = copyTail = copy;
    }
    else
    {
        copyTail->next = copy;
        copyTail = copyTail->next;
    }
    cur = next;
}
return copyHead;
}
  • El código total es el siguiente:
struct Node* copyRandomList(struct Node* head) {
    struct Node* cur = head;
    //1、拷贝节点链接在原节点后面
    while (cur)
    {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;
        copy->next = cur->next;
        cur->next = copy;
        cur = cur->next->next;
    }
    //2、更新拷贝节点的random
    cur = head;
    while (cur)
    {
        struct Node* copy = cur->next;
        if (cur->random == NULL)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }
        cur = cur->next->next;
    }
    //3、拷贝节点剪下来,链接到一起
    cur = head;
    struct Node* copyTail = NULL;
    struct Node* copyHead = NULL;
    while (cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;
        cur->next = next;
        if (copyTail == NULL)
        {
            copyHead = copyTail = copy;
        }
        else
        {
            copyTail->next = copy;
            copyTail = copyTail->next;
        }
        cur = next;
    }
    return copyHead;
}

Supongo que te gusta

Origin blog.csdn.net/bit_zyx/article/details/123659504
Recomendado
Clasificación