logseq_notes/pages/OJ notes/pages/Leetcode Remove-Nth-Node-From-End-of-List.md
2023-06-14 14:27:22 +08:00

3.3 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_problems #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;
}
};