notes/OJ notes/pages/Leetcode Remove-Nth-Node-From-End-of-List.md
2022-09-06 20:22:48 +08:00

3.4 KiB

Leetcode Remove-Nth-Node-From-End-of-List

2022-07-13 09:31

Algorithms:

#algorithm #two_pointers

Data structures:

#DS #linked_list

Difficulty:

#coding_problem #difficulty_medium

Additional tags:

#leetcode #CS_list_need_understanding

Revisions:

N/A


Problem

Given the head of a linked list, remove the nth node from the end of the list and return its head.

Examples

Example 1:

Input: head = [1,2,3,4,5], n = 2 Output: [1,2,3,5]

Example 2:

Input: head = [1], n = 1 Output: []

Example 3:

Input: head = [1,2], n = 1 Output: [1]

Constraints

  • The number of nodes in the list is sz.
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz

Thoughts

[!summary] This is a #two_pointers problem

#TODO: Understand the two-pointer method

Initially, I thought I use one pointer to remember how long the list is, and use another to traverse there, and remove.

Two pointers method

To finish this in one pass, i need to somehow make the two pointers reach the end at the same time.

We can let fast go n step first, such that when fast comes to the end, slow gets to the Nth node from the last.

To find the 2nd from the last:


slow
|
v
1 -> 2 -> 3 -> 4 -> 5
|         ^
|----N----|
					fast

Solution

Two pointers method

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
  ListNode *removeNthFromEnd(ListNode *head, int n) {
    ListNode *pre = new ListNode(0, head);
    ListNode *slow = pre;
    ListNode *fast = slow;

    while (n) {
      fast = fast->next;
      n--;
    }

    while (fast->next) {
      slow = slow->next;
      fast = fast->next;
    }

    fast = slow->next;
    slow->next = slow->next->next;
    delete fast;

    return pre->next;
  }
};

Initial iteration:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
  ListNode *removeNthFromEnd(ListNode *head, int n) {
    // Use one pointer to get length, another to traverse there
    int count = 1;
    ListNode *fast = head;

    while (1) {
      if (fast->next && fast->next->next) {
        fast = fast->next->next;
        count += 2;
      } else if (!fast->next) {
        break;
      } else {
        count += 1;
        break;
      }
    }

    count = count - n;
    ListNode *pre = new ListNode(0, head);
    ListNode *slow = pre;
    while (count) {
      slow = slow->next;
      count--;
    }

    fast = slow->next;
    slow->next = slow->next->next;
    delete fast;

    return pre->next;
  }
};