1. Problem Statement (Simple Explanation):
You are given the head of a singly linked list and an integer n.
You must remove the n-th node from the end of the list, and return the (possibly new) head.
The list has at least 1 node.
1 <= n <= size of list.
2. Examples:
Example 1:
Input: head = [1,2,3,4,5], n = 2
The 2nd node from the end is 4 (nodes from end: 5(1st), 4(2nd)).
Output: [1,2,3,5]
Example 2:
Input: head = [1], n = 1
The 1st node from the end is 1 itself.
Output: []
Example 3:
Input: head = [1,2], n = 1
The 1st node from the end is 2.
Output: [1]
Constraints:
1 <= sz <= 30
0 <= Node.val <= 1000
1 <= n <= sz
Follow-up: Can you do it in one pass?
3. Approach 1 – Two-pass (Count then Remove) – Simple but Two Passes:
Idea:
First pass: compute the length L of the list.
The node to remove is at position L - n (0-based) or L - n + 1 (1-based) from the start.
Second pass: walk to the node just before the node to delete and adjust pointers.
This is easy but requires two passes over the list.
Pseudo-code (Two-pass):
Space: O(1).
4. Approach 2 – One-pass Two-pointer Technique (Fast/Slow) – Optimal:
This is the standard solution for the follow-up.
Intuition:
Use two pointers:
fast
slow
Steps:
Move fast pointer n steps ahead.
Then move both fast and slow together until fast reaches the end.
At that point, slow will be just before the node to delete.
Adjust slow.next to skip the target node.
To handle removing the head (when the removed node is the first), use a dummy node before head.
Algorithm (Step-by-Step):
Create a dummy node:
dummy.next = head
Both fast and slow start at dummy.
Move fast ahead n + 1 steps (so that the gap between fast and slow remains n nodes and slow lands just before the node to delete).
Alternatively, move fast n steps from head while slow starts from dummy; equivalent variants exist. A common pattern is:
Move fast n steps starting from dummy.next.
Then move both until fast.next == null.
We’ll use a clear variant: move fast n steps from the head, starting fast = head, slow = dummy.
Then move both pointers one step at a time:
While fast is not null:
fast = fast.next
slow = slow.next
After the loop, slow.next is the node to be removed.
Remove it:
slow.next = slow.next.next
Return dummy.next.
Pseudo-code (One-pass, clear variant):
Complexity:
Let L be the length of the list:
Time: O(L)
Space: O(1)
5. Java code:
8. Python code:
9. JavaScript code:







Comments
Post a Comment