How to Remove Nth Node From End of List in C/C++?


Remove the nth node from the end of a singly linked list and return its head. For example, input: 1-2-3-4-5, and n = 2. Removing the second node from the end, the linked list becomes 1-2-3-5. You can assume the n will always be valid (less than the length of the linked list).

Two passes

The straightforward two-passes will be first to detect the length of the linked list and the second pass is to delete its n-th node. As the length of the linked list is no known without a pass, it would be difficult to know which node from the end to delete in the first place.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        int r = 0;
        auto p = head;
        // first pass - get the length        
        while (head != NULL) {
            r ++;
            head = head->next;
        }
        // removing the head
        if (r == n) {
            p = p->next;
            return p;
        }
        head = p;
        // second pass, locate the node
        for (int i = 0; i < r - n - 1; i ++) {
            head = head->next;
        }
        // and delete it
        head->next = head->next->next;
        return p; // stored head
    }
};
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        int r = 0;
        auto p = head;
        // first pass - get the length        
        while (head != NULL) {
            r ++;
            head = head->next;
        }
        // removing the head
        if (r == n) {
            p = p->next;
            return p;
        }
        head = p;
        // second pass, locate the node
        for (int i = 0; i < r - n - 1; i ++) {
            head = head->next;
        }
        // and delete it
        head->next = head->next->next;
        return p; // stored head
    }
};

One pass

The trick of using One-pass is to have two pointers, fast and slow one. The slow pointer will only advance itself after n-th round, so when the fast pointer reaches the end, the slow pointer will be exactly n-th node from the end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        auto front = head, back = head;
        while (front) {
            front = front->next;
            if (n-- < 0) {
                back = back->next;
            }
        }
        if (n == 0) {
            head = head->next;
        } else {
            back->next = back->next->next;
        }
        return head;
    }
};
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        auto front = head, back = head;
        while (front) {
            front = front->next;
            if (n-- < 0) {
                back = back->next;
            }
        }
        if (n == 0) {
            head = head->next;
        } else {
            back->next = back->next->next;
        }
        return head;
    }
};

The second method is obviously faster. Both methods need to make deleting-the-head a special case.

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
373 words
Last Post: Break a Sentence into Words (Word Break Algorithms) - DFS, BFS and DP
Next Post: How to Reverse Linked List within Interval? (C/C++)

The Permanent URL is: How to Remove Nth Node From End of List in C/C++?

Leave a Reply