Introduction to algorithm C-19. Delete the penultimate node of the linked list

Keywords: C Algorithm linked list

LeetCode problem brushing - algorithm learning plan (Introduction)

Title Description

Introduction of ideas

Personal idea: first find out which node to delete is the first node of the linked list (index=len + 1 -n). If it is the first node (head), move the head to the right (head = head - > next); If it is not the head node, use a linked list pointer tmp to point to the previous node of the node to be deleted, and finally connect the next node of the next node of tmp to the back of tmp (tmp - > next = tmp - > next - > next).

My first correct submission

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

//Get linked list length
int GetListNodeLen(struct ListNode* head)
{
    int len = 1;
    struct ListNode *tmp = head; 
    if(tmp == NULL)
        return 0;
    while(tmp->next != NULL)
    {
        len++;
        tmp = tmp->next;
    }
    return len;
}

struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
    int i = 0;
    struct ListNode *tmp = head; 
    int len = GetListNodeLen(head);   //Get linked list length
    int index = len + 1 - n;          //Serial number of the linked list node to be deleted (starting from 1)
    if(index == 1)                    //If the node to be deleted is a header node
    {
        head = head -> next;
        return head;
    }
    for(i = 1; i < index - 1; i++)    //Move tmp to the previous node where you want to delete the node
    {
        tmp = tmp->next;
    }
    tmp->next = tmp->next->next;      //Connect the next node of the node to be deleted after its previous node
    return head;
}

Official version

Here is the official version

Method 1: calculate the length of the linked list

An easy way to think of is that we first traverse the linked list from the node to get the length L of the linked list. Then we traverse the linked list from the first node. When we traverse to the L − n+1 node, it is the node we need to delete.
In order to be consistent with n in the title, the number of nodes starts from 1, and the head node is the node numbered 1.
In order to facilitate the deletion operation, we can traverse L − n+1 nodes from the dummy node. When traversing the L − n+1 node, its next node is the node we need to delete, so we only need to modify the pointer once to complete the deletion operation.
——Author: leetcode solution
Link: https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/

This is the method I used, but dummy nodes (dummy - > Val = 0, dummy - > next = head;) are used here

int getLength(struct ListNode* head) {
    int length = 0;
    while (head) {
        ++length;
        head = head->next;
    }
    return length;
}

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode* dummy = malloc(sizeof(struct ListNode));
    dummy->val = 0, dummy->next = head;
    int length = getLength(head);
    struct ListNode* cur = dummy;
    for (int i = 1; i < length - n + 1; ++i) {
        cur = cur->next;
    }
    cur->next = cur->next->next;
    struct ListNode* ans = dummy->next;
    free(dummy);
    return ans;
}

Author: LeetCode-Solution
 Link: https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/
Source: force buckle( LeetCode)
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Complexity analysis
Time complexity: O(L), where l is the length of the linked list.
Space complexity: O(1).

Method 2: stack

We can also put all nodes on the stack in turn while traversing the linked list. According to the "first in, last out" principle of the stack, we pop up that the nth node on the stack is the node to be deleted, and the current node on the top of the stack is the precursor node of the node to be deleted. In this way, the deletion operation becomes very convenient.
——Author: leetcode solution
Link: https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/

struct Stack {
    struct ListNode* val;
    struct Stack* next;
};

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode* dummy = malloc(sizeof(struct ListNode));
    dummy->val = 0, dummy->next = head;
    struct Stack* stk = NULL;
    struct ListNode* cur = dummy;
    while (cur) {
        struct Stack* tmp = malloc(sizeof(struct Stack));
        tmp->val = cur, tmp->next = stk;
        stk = tmp;
        cur = cur->next;
    }
    for (int i = 0; i < n; ++i) {
        struct Stack* tmp = stk->next;
        free(stk);
        stk = tmp;
    }
    struct ListNode* prev = stk->val;
    prev->next = prev->next->next;
    struct ListNode* ans = dummy->next;
    free(dummy);
    return ans;
}

Author: LeetCode-Solution
 Link: https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/
Source: force buckle( LeetCode)
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Complexity analysis
Time complexity: O(L), where l is the length of the linked list.
Space complexity: O(L), where l is the length of the linked list. It is mainly the overhead of the stack.

Method 3: double pointer

We can also solve this problem without preprocessing the length of the linked list and using the constant space. See Official explanation

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode* dummy = malloc(sizeof(struct ListNode));
    dummy->val = 0, dummy->next = head;
    struct ListNode* first = head;
    struct ListNode* second = dummy;
    for (int i = 0; i < n; ++i) {
        first = first->next;
    }
    while (first) {
        first = first->next;
        second = second->next;
    }
    second->next = second->next->next;
    struct ListNode* ans = dummy->next;
    free(dummy);
    return ans;
}

Author: LeetCode-Solution
 Link: https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/
Source: force buckle( LeetCode)
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Complexity analysis
Time complexity: O(L), where l is the length of the linked list.
Space complexity: O(1).

Here is my failed submission record

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

//Get linked list length
int GetListNodeLen(struct ListNode* head)
{
    int len = 1;
    struct ListNode *tmp = head; 
    if(tmp == NULL)
        return 0;
    while(tmp->next != NULL)
    {
        len++;
        tmp = tmp->next;
    }
    return len;
}

struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
    int i = 0;
    struct ListNode *tmp = head; 
    int len = GetListNodeLen(head);   //Get linked list length
    int index = len + 1 - n;          //Serial number of the linked list node to be deleted (starting from 1)
    if(index == 1)                    //If the node to be deleted is a header node
    {
        tmp = tmp -> next;
        return head;
    }
    for(i = 1; i < index - 1; i++)    //Move tmp to the previous node where you want to delete the node
    {
        tmp = tmp->next;
    }
    tmp->next = tmp->next->next;      //Connect the next node of the node to be deleted after its previous node
    return head;
}

This code is actually different from the successfully submitted version in two lines: (struct ListNode *tmp = head;)

error code

    if(index == 1)                    //If the node to be deleted is a header node
    {
        tmp = tmp -> next;
        return head;
    }

After submitting the successful version, by contrast, I found that the above way of writing, the head is overwritten by me... [you can have no header node, but you can't have no header pointer]
This error can be avoided through the dummy node in the official problem solution, so you don't have to make the following judgment.

    if(index == 1)                    //If the node to be deleted is a header node
    {
        head = head -> next;
        return head;
    }

Posted by mchaggis on Thu, 04 Nov 2021 09:54:12 -0700