Remove Nth Node from End of List in DSA C# - Time & Space Complexity
We want to understand how the time needed to remove the nth node from the end of a linked list changes as the list grows.
How does the number of steps grow when the list gets longer?
Analyze the time complexity of the following code snippet.
public ListNode RemoveNthFromEnd(ListNode head, int n) {
ListNode fast = head, slow = head;
for (int i = 0; i < n; i++) {
fast = fast.next;
}
if (fast == null) return head.next;
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}
This code removes the nth node from the end of a singly linked list by using two pointers moving through the list.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Moving pointers through the list using loops.
- How many times: The first loop moves the fast pointer n times; the second loop moves both pointers until fast reaches the end, which can be up to (length - n) times.
As the list size grows, the number of steps to move pointers grows roughly in proportion to the list length.
| Input Size (length) | Approx. Operations |
|---|---|
| 10 | About 10 steps to move pointers |
| 100 | About 100 steps to move pointers |
| 1000 | About 1000 steps to move pointers |
Pattern observation: The steps increase linearly as the list gets longer.
Time Complexity: O(n)
This means the time to remove the nth node from the end grows in a straight line with the size of the list.
[X] Wrong: "Since we only move the fast pointer n times first, the time is O(n) where n is the position from the end, not the list length."
[OK] Correct: The second loop moves the pointers through the rest of the list, which depends on the total list length, not just n.
Understanding this time complexity helps you explain how efficient your solution is when working with linked lists, a common topic in interviews.
"What if we used a single pass with a stack instead of two pointers? How would the time complexity change?"
Practice
Remove Nth Node from End of List ask you to do?Solution
Step 1: Understand the problem statement
The problem asks to remove the node that is nth from the end of a singly linked list.Step 2: Clarify what removal means
Removal means unlinking that node so the list skips it, keeping the rest intact.Final Answer:
Delete the node that is the nth from the end in a linked list -> Option AQuick Check:
Remove nth from end = Delete nth from end [OK]
- Confusing nth from end with nth from start
- Thinking it means reversing the list
- Trying to find value instead of removing node
Solution
Step 1: Check for public access modifiers
public class ListNode { public int val; public ListNode next; public ListNode(int x) { val = x; next = null; } } uses public class and public members, which is correct for external access.Step 2: Verify constructor and member initialization
public class ListNode { public int val; public ListNode next; public ListNode(int x) { val = x; next = null; } } correctly initializes val and next in constructor; others miss public or use struct incorrectly.Final Answer:
public class ListNode { public int val; public ListNode next; public ListNode(int x) { val = x; next = null; } } -> Option DQuick Check:
Proper class with public members = public class ListNode { public int val; public ListNode next; public ListNode(int x) { val = x; next = null; } } [OK]
- Missing public keyword causing access errors
- Using struct instead of class for linked list node
- Not initializing next to null in constructor
Solution
Step 1: Identify the 2nd node from the end
The list is 1->2->3->4->5. Counting from end: 5 (1st), 4 (2nd). So node with value 4 is to be removed.Step 2: Remove node with value 4
Link node 3's next to node 5, skipping node 4. Result: 1->2->3->5->null.Final Answer:
1 -> 2 -> 3 -> 5 -> null -> Option CQuick Check:
Remove 2nd from end (4) = 1->2->3->5 [OK]
- Removing the wrong node counting from start
- Removing node with value 3 instead of 4
- Not updating links correctly causing broken list
public ListNode RemoveNthFromEnd(ListNode head, int n) {
ListNode fast = head;
ListNode slow = head;
for (int i = 0; i < n; i++) {
fast = fast.next;
}
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return head;
}Solution
Step 1: Analyze fast pointer movement
Fast moves n steps ahead. If n equals list length, fast becomes null.Step 2: Check for null fast before accessing fast.next
Code does not check if fast is null before while loop, causing NullReferenceException.Final Answer:
Does not handle case when fast becomes null after initial loop -> Option AQuick Check:
Null fast after n steps = bug [OK]
- Ignoring null check for fast pointer
- Moving slow pointer before fast is properly positioned
- Returning wrong node as new head
Solution
Step 1: Understand removing 1st node from end in single-node list
Removing last node means list becomes empty.Step 2: Resulting list after removal
Since only node is removed, list is now null (empty).Final Answer:
null (empty list) -> Option BQuick Check:
Remove only node = empty list [OK]
- Returning original list instead of empty
- Expecting error instead of empty list
- Trying to access next node which does not exist
Ready to prove it?
Pass the test and this pattern moves unknown
