Back to Linked List

Remove Nth Node from End

Remove Nth Node From End of List

🧩 Problem Statement

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

šŸ”¹ Example 1:

Input:

head = [1,2,3,4,5], n = 2

Output:

[1,2,3,5]

šŸ”¹ Example 2:

Input:

head = [1], n = 1

Output:

[]

šŸ” Approaches

1. Two Pointers (One Pass)

We can use two pointers, first and second, separated by n nodes.
When first reaches the end, second will be exactly at the node before the one we want to remove.

✨ Intuition

  • Use a dummy node pointing to head (to handle edge case where head itself is removed).
  • Initialize first = dummy, second = dummy.
  • Move first n + 1 steps ahead. Now the gap between first and second is n + 1.
  • Move both first and second one step at a time until first becomes null.
  • At this point, second is at the node before the target.
  • Remove the target: second.next = second.next.next.

šŸ”„ Algorithm Steps

  1. Create dummy node with dummy.next = head.
  2. Set first = dummy, second = dummy.
  3. Move first n + 1 times forward.
  4. While first is not null:
  • first = first.next
  • second = second.next
  1. second.next = second.next.next
  2. Return dummy.next.

ā³ Time & Space Complexity

  • Time Complexity: $O(L)$, where $L$ is length of list. We make one pass.
  • Space Complexity: $O(1)$.

šŸš€ Code Implementations

C++

/**
* 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* dummy = new ListNode(0, head);
ListNode* first = dummy;
ListNode* second = dummy;
for (int i = 0; i <= n; i++) {
first = first->next;
}
while (first != nullptr) {
first = first->next;
second = second->next;
}
ListNode* temp = second->next;
second->next = second->next->next;
delete temp; // Free memory
return dummy->next;
}
};

Python

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummy = ListNode(0, next=head)
left = dummy
right = head
while n > 0 and right:
right = right.next
n -= 1
while right:
left = left.next
right = right.next
# delete
left.next = left.next.next
return dummy.next

Java

/**
* Definition for singly-linked list.
* public class ListNode {
*     int val;
*     ListNode next;
*     ListNode() {}
*     ListNode(int val) { this.val = val; }
*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode first = dummy;
ListNode second = dummy;
for (int i = 0; i <= n; i++) {
first = first.next;
}
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
}

šŸŒ Real-World Analogy

Relay Race Batons:

Imagine two runners with a solid stick connecting them that is exactly n meters long.

  • They start at the beginning.
  • They run together.
  • When the front runner hits the finish line, the back runner is exactly n meters away from the finish.
  • The back runner picks up the object at that spot.

šŸŽÆ Summary

āœ… One Pass: Efficiently finds the node.
āœ… Dummy Node: Simplifies edge cases (e.g., removing head).

Solution Code
O(n) TimeO(1) Space
#include <iostream>

using namespace std;

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 *dummy = new ListNode(0, head);
    ListNode *first = dummy;
    ListNode *second = dummy;

    for (int i = 0; i <= n; i++) {
      first = first->next;
    }

    while (first != nullptr) {
      first = first->next;
      second = second->next;
    }

    ListNode *temp = second->next;
    second->next = second->next->next;
    delete temp;

    return dummy->next;
  }
};

void printList(ListNode *head) {
  while (head) {
    cout << head->val << (head->next ? "->" : "");
    head = head->next;
  }
  cout << endl;
}

int main() {
  Solution sol;
  ListNode *head = new ListNode(
      1, new ListNode(2, new ListNode(3, new ListNode(4, new ListNode(5)))));
  cout << "Original: ";
  printList(head);

  head = sol.removeNthFromEnd(head, 2);

  cout << "After removing 2nd from end: ";
  printList(head); // Should start with 1->2->3->5
  return 0;
}
SYSTEM STABLE
UTF-8 • STATIC_RENDER