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
dummynode pointing tohead(to handle edge case where head itself is removed). - Initialize
first = dummy,second = dummy. - Move
firstn + 1steps ahead. Now the gap betweenfirstandsecondisn + 1. - Move both
firstandsecondone step at a time untilfirstbecomesnull. - At this point,
secondis at the node before the target. - Remove the target:
second.next = second.next.next.
š„ Algorithm Steps
- Create
dummynode withdummy.next = head. - Set
first = dummy,second = dummy. - Move
firstn + 1times forward. - While
firstis not null:
first = first.nextsecond = second.next
second.next = second.next.next- 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
nmeters 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 STABLEUTF-8 ⢠STATIC_RENDER