Given the head of a linked list, remove the nth 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: []
Example 3:
Input: head = [1,2], n = 1 Output: [1]
Constraints:
- The number of nodes in the list is
sz. 1 <= sz <= 300 <= Node.val <= 1001 <= n <= sz
Problem Description
The problem presents us with a linked list and requires us to remove the nth node from the end of the list. A linked list is a linear collection of elements called nodes, where each node contains data and a reference (or link) to the next node in the sequence. The head of a linked list refers to the first node in this sequence. Our goal is to remove the nth node from the last node and return the updated list’s head.
In simple terms, if we were to count nodes starting from the last node back to the first, we need to find and remove the node that sits at position ‘n’. For example, if the linked list is 1->2->3->4->5 and n is 2, the resulting linked list after the operation should be 1->2->3->5, since the 4 is the 2nd node from the end.
The challenge with this task is that we can’t navigate backwards in a singly linked list, so we need to figure out a way to reach the nth node from the end only by moving forward.
Intuition
To address the problem, we apply a two-pointer approach, which is a common technique in linked list problems. The intuition here lies in maintaining two pointers that we’ll call fast and slow. Initially, both of these pointers will start at a dummy node that we create at the beginning of the list, which is an auxiliary node to simplify edge cases, such as when the list contains only one node, or when we need to remove the first node of the list.
The fast pointer advances n nodes into the list first. Then, both slow and fast pointers move at the same pace until fast reaches the end of the list. At this point, slow will be right before the node we want to remove. By updating the next reference of the slow pointer to skip the target node, we effectively remove the nth node from the end of the list.
The use of a dummy node is a clever trick to avoid having to separately handle the special case where the node to remove is the first node of the list. By ensuring that our slow pointer starts before the head of the actual list, we can use the same logic for removing the nth node, regardless of its position in the list.
After we’ve completed the removal, we return dummy.next, which is the updated list’s head, after the dummy node.
Solution Approach
The solution implements an efficient approach to solving the problem by using two pointers and a dummy node. Here’s a step-by-step walkthrough of the implementation:
- Create a Dummy Node: A dummy node is created and its
nextpointer is set to theheadof the list. This dummy node serves as an anchor and helps to simplify the removal process, especially if theheadneeds to be removed.dummy = ListNode(next=head) - Initialize Two Pointers: Two pointers
fastandsloware introduced and both are set to the dummy node. This allows for them to start from the very beginning of the augmented list (which includes the dummy node).fast = slow = dummy - Advance Fast Pointer: The
fastpointer advancesnsteps into the list.for _ in range(n): fast = fast.next - Move Both Pointers: Both pointers then move together one step at a time until the
fastpointer reaches the end of the list. By this time,slowis at the position right before the nth node from the end.while fast.next: slow, fast = slow.next, fast.next - Remove the Target Node: Once
slowis in position, itsnextpointer is changed to skip the target node which effectively removes it from the list.slow.next = slow.next.next - Return Updated List: Finally, the next node after the dummy is returned as the new head of the updated list.
return dummy.next
The algorithm fundamentally relies on the two-pointer technique to find the nth node from the end. The use of a dummy node facilitates the removal of nodes, including the edge case of the head node, with a consistent method. The space complexity is O(1) since no additional space is required aside from the pointers, and the time complexity is O(L), where L is the length of the list, as we traverse the list with two pointers in a single pass.
Example Walkthrough
Let’s use the linked list 1->2->3->4->5 as an example to illustrate the solution approach described above, where n is 2, meaning we want to remove the 2nd node from the end, which is the node with the value 4. Here’s how the algorithm would be applied:
- Create a Dummy Node: We create a dummy node with
Noneas its value and link it to the head of our list. Our list now looks likedummy->1->2->3->4->5. - Initialize Two Pointers: We set both
fastandslowpointers to the dummy node. They both point todummyinitially. - Advance Fast Pointer: As
nis 2, we advance thefastpointernsteps into the list.fastbecomes:- After 1st step:
fastpoints to1 - After 2nd step:
fastpoints to2
- After 1st step:
- Move Both Pointers: Now we move both
slowandfastpointers together one step at a time untilfastreaches the last node:slowpoints todummyandfastpoints to2(Start)slowpoints to1andfastpoints to3slowpoints to2andfastpoints to4slowpoints to3andfastpoints to5(End)
slowpoints to the3andfastpoints to the last node5. - Remove the Target Node: Now,
slow.nextis pointing to the node4, which we want to remove. We updateslow.nextto point toslow.next.next(which is5), effectively removing the4from the list. - Return Updated List: Finally, we return the next node after the dummy, which is the
headof our updated list (1->2->3->5). The updated list after removal is as follows:1->2->3->5.
The problem is solved in one pass and the node is successfully removed according to the given constraints.
Solution Implementation
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *prev;
ListNode *dummy = new ListNode();
dummy->next = head;
prev = dummy;
int t = 0;
while(prev != NULL){
prev = prev->next;
t++;
}
if(t == 1){
head = NULL;
return head;
}
prev = dummy;
t = t - n;
for(int i = 0; i<t-1; i++){
prev = prev->next;
}
prev->next = prev->next->next;
return dummy->next;
}
};
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
// Creating a dummy node to simplify the removal of head
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode slow = dummy;
ListNode fast = dummy;
// 1. Move fast n+1 step forward so that slow is in front of the node being deleted
for (int i = 0; i <= n; i++) {
fast = fast.next;
}
// 2. Move fast to the end, and slow to the node before the deleted one
while (fast != null) {
slow = slow.next;
fast = fast.next;
}
// 3. Remove the nth node from the end (slow.next points to it)
slow.next = slow.next.next;
// Returning a new head (dummy.next could have changed if the head was deleted)
return dummy.next;
}
}
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
count = 0
curr = head
dummy = curr
while curr:
count += 1
curr = curr.next
# if count == 1 and n == 1:
# return None
if count == n:
head = head.next
remove = count - n
count = 0
while dummy:
count +=1
if count == remove:
dummy.next = dummy.next.next
break
dummy = dummy.next
return head
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode* temp=head;
int count=0;
while(temp!=NULL){
temp=temp->next;
count=count+1;
}
if (count == n) {
struct ListNode* newHead = head->next;
free(head);
return newHead;
}
struct ListNode* tempa=head;
for(int i=0;i<count-n-1;i++){
tempa=tempa->next;
}
struct ListNode* tem=tempa->next;
tempa->next=tempa->next->next;
free(tem);
return head;
}
public class Solution {
public ListNode RemoveNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
// Move fast pointer n+1 steps ahead
for (int i = 0; i <= n; i++) {
fast = fast.next;
}
// Move both pointers until fast reaches the end
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
// Remove the nth node from the end
slow.next = slow.next.next;
return dummy.next;
}
}
var removeNthFromEnd = function(head, n) {
let fast = head, slow = head
for (let i = 0; i < n; i++) fast = fast.next
if (!fast) return head.next
while (fast.next) fast = fast.next, slow = slow.next
slow.next = slow.next.next
return head
};
// We assume ListNode is provided by the environment and should not be redefined.
function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
// Create a dummy node to simplify edge cases
const dummy = new ListNode(0);
dummy.next = head;
let first: ListNode | null = dummy;
let second: ListNode | null = dummy;
// Move the first pointer n+1 steps ahead
for (let i = 0; i <= n; i++) {
first = first?.next ?? null;
}
// Move both pointers until the first pointer reaches the end
while (first !== null) {
first = first.next;
second = second?.next ?? null;
}
// Remove the nth node from the end
second!.next = second?.next?.next ?? null;
// Return the new head of the list
return dummy.next;
}
class Solution {
/**
* @param ListNode $head
* @param Integer $n
* @return ListNode
*/
function removeNthFromEnd($head, $n) {
$dummy = new ListNode(0, $head);
$first = $dummy;
$second = $dummy;
for ($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;
}
}
class Solution {
func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
let node = ListNode(0)
node.next = head
var prev: ListNode? = node
var post: ListNode? = node
for _ in 0..<n {
guard let next = post?.next else { continue }
post = next
}
while let postNext = post?.next, let prevNext = prev?.next {
prev = prevNext
post = postNext
}
prev!.next = prev!.next!.next
return node.next
}
}
class Solution {
fun removeNthFromEnd(head: ListNode, n: Int): ListNode? {
head0.next = head
var node: ListNode? = head0
var steps = getNodeCount(head0) - n
while (steps > 1) {
steps--
node = node?.next
}
node?.next = node?.next?.next
return head0.next
}
private fun getNodeCount(head: ListNode): Int {
var count = 0
var node: ListNode? = head
while (node != null) {
node = node.next
count++
}
return count
}
companion object {
val head0 = ListNode(0)
}
}
class Solution {
ListNode? removeNthFromEnd(ListNode? head, int n) {
final dummy = ListNode(0, head);
ListNode? left = dummy;
ListNode? right = head;
while(n > 0 && right != null) {
right = right.next;
n--;
}
while(right != null) {
right = right.next;
left = left?.next;
}
left?.next = left.next?.next;
return dummy.next;
}
}
func removeNthFromEnd(head *ListNode, n int) *ListNode {
// Создаем фиктивный узел перед головным узлом
dummy := &ListNode{0, head}
slow, fast := dummy, dummy
// Перемещаем fast на n+1 шаг вперед
for i := 0; i <= n; i++ {
fast = fast.Next
}
// Двигаем slow и fast одновременно
for fast != nil {
slow = slow.Next
fast = fast.Next
}
// Удаляем узел, на который указывает slow.Next
slow.Next = slow.Next.Next
// Возвращаем обновленный список, пропуская фиктивный узел
return dummy.Next
}
Time and Space Complexity
The given code is designed to remove the nth node from the end of a singly linked list. It employs the two-pointer technique with fast and slow pointers. Let’s analyze the time and space complexity:
Time Complexity
The time complexity is determined by the number of operations required to traverse the linked list. There are two main steps in this algorithm:
- The
fastpointer movesnsteps ahead – this takesO(n)time. - Both
fastandslowpointers move together untilfastreaches the last node. The worst-case scenario is whennis 1, which would cause theslowpointer to traverse the entire list of sizeL(list length), takingO(L)time.
Since the list is traversed at most once, the overall time complexity is O(L).
Space Complexity
The space complexity is determined by the amount of additional space used by the algorithm, which does not depend on the input size:
- The
dummynode and the pointers (fastandslow) use constant extra space, regardless of the linked list’s size. - Therefore, the space complexity is
O(1)for the extra space used by the pointers and the dummy node.

Excellent read, I just passed this onto a colleague who was doing some research on that. And he just bought me lunch as I found it for him smile So let me rephrase that: Thanks for lunch!
Sir plese solve the problem 🙏