Deletion is rewiring: find the node BEFORE the target → prev.next = prev.next.next.
Focus on recognizing:
“Remove kth node” / “one pass required” → gap trick between two pointers
Pattern 1: Remove N-th From End (One Pass)
Removing the 2nd-from-end of [1,2,3,4,5] — the fixed gap parks slow exactly before node 3. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Remove Nth Node From End
Delete the n-th node from the end of a list — compare a one-pass two-pointer gap trick with a two-pass length-then-walk approach.
Advance fast n+1 nodes ahead (using a dummy head so the head itself can be deleted), then walk both until fast is null; slow sits just before the target, which you then bypass.
1
dummy → head; fast = slow = dummy
2
for i in 0..n: // gap of n+1
3
fast = fast.next
4
while fast: // walk together
5
fast = fast.next; slow = slow.next
6
slow.next = slow.next.next // remove
1
# pass 1: measure
2
len = 0; cur = head
3
while cur: len++; cur = cur.next
4
# pass 2: stop before target
5
target = len - n // 0-indexed
6
cur = dummy; walk target times
7
cur.next = cur.next.next
Fast gets an n-step head start; when it hits the end, slow stands right before the victim:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode fast = dummy, slow = dummy;
for (int i = 0; i <= n; i++) // n + 1 steps of gap
fast = fast.next;
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next; // remove target
return dummy.next;
}def remove_nth_from_end(head, n):
dummy = ListNode(0, head)
fast = slow = dummy
for _ in range(n + 1): # n + 1 steps of gap
fast = fast.next
while fast:
fast = fast.next
slow = slow.next
slow.next = slow.next.next # remove target
return dummy.nextListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(0, head);
ListNode *fast = &dummy, *slow = &dummy;
for (int i = 0; i <= n; i++) // n + 1 steps of gap
fast = fast->next;
while (fast) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next; // remove target
return dummy.next;
}function removeNthFromEnd(head, n) {
const dummy = new ListNode(0, head);
let fast = dummy,
slow = dummy;
for (let i = 0; i <= n; i++) fast = fast.next; // gap n+1
while (fast) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next; // remove target
return dummy.next;
}The dummy node makes “remove the head” a no-special-case operation.
Pattern 2: Remove N-th From Start
Walk n−1 steps and relink. Watch the head-removal edge case. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Remove N-th Node From The Start
Remove the n-th node (1-indexed) from the head of a linked list.
Walk n-1 steps to land on the target, then unlink it by wiring prev.next past it. If prev is null the head is being removed, so return head.next.
1
prev = null; cur = head
2
for i in 1..n-1: cur = cur.next
3
if prev == null: return head.next // removing head
4
prev.next = cur.next
Same rewiring, direct index walk:
public ListNode removeNth(ListNode head, int n) { // 1-indexed
if (n == 1) return head.next;
ListNode cur = head;
for (int i = 1; i < n - 1; i++)
cur = cur.next; // stop BEFORE target
cur.next = cur.next.next;
return head;
}def remove_nth(head, n): # 1-indexed
if n == 1:
return head.next
cur = head
for _ in range(n - 2):
cur = cur.next # stop BEFORE target
cur.next = cur.next.next
return headListNode* removeNth(ListNode* head, int n) { // 1-indexed
if (n == 1) return head->next;
ListNode* cur = head;
for (int i = 1; i < n - 1; i++)
cur = cur->next; // stop BEFORE target
cur->next = cur->next->next;
return head;
}function removeNth(head, n) {
// 1-indexed
if (n === 1) return head.next;
let cur = head;
for (let i = 1; i < n - 1; i++) cur = cur.next; // before target
cur.next = cur.next.next;
return head;
}Pattern 3: Delete Given Node (No Head Access)
Steal the neighbour’s value, skip past it — identity swap trick. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Delete Node In A Linked List
Delete a node from a singly linked list given only a pointer to that node (no head).
Since the previous node is unreachable, copy the successor's value into the target and then bypass the successor. Result looks identical value-wise. It cannot work when the target is the tail.
1
// target = the 1, head unknown
2
node.val = node.next.val
3
node.next = node.next.next
Copy the NEXT node’s value into this one, then skip it:
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
}def delete_node(node):
node.val = node.next.val
node.next = node.next.nextvoid deleteNode(ListNode* node) {
node->val = node->next->val;
node->next = node->next->next;
}function deleteNode(node) {
node.val = node.next.val;
node.next = node.next.next;
}Works because the target is never the tail — guaranteed by these problems.
Common Mistakes
Stopping ON the target instead of before it.
You can’t delete a node without access to its predecessor (except the value-copy trick).
Counting length first.
Two passes work but interviews ask for one — the gap trick is the expected answer.
Losing the head reference.
Return dummy.next, not head — head may have been the removed node.
Complexity
| Operation | Time | Space |
|---|---|---|
| From end (gap trick) | O(n) | O(1) |
| From start | O(n) | O(1) |
| Given node | O(1) | O(1) |
Premium Content
Unlock Remove Nth Node and all premium lessons with a subscription.
From ₹199.99/year — See plans