Two Pass
Intuition
The straightforward approach is to first calculate the total length of the list, then determine the position of the node to remove from the beginning. The node to remove is at position length - n from the start (0-indexed). We traverse again to the node just before that position and adjust the pointers to skip the target node. A dummy node simplifies edge cases such as removing the head.
Algorithm
- Traverse the list once to calculate its total length.
- Create a dummy node pointing to `head`.
- Compute the position from the start: `length - n`.
- Traverse from the dummy node to the node just before position `length - n`.
- Set that node's `next` to `next.next`, skipping the target node.
- Return `dummy.next`.
O(n)SpaceO(1)Code (C++ · Java · Python · Go)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
int length = 0;
ListNode* curr = head;
while (curr != nullptr) {
length++;
curr = curr->next;
}
ListNode dummy(0, head);
curr = &dummy;
for (int i = 0; i < length - n; i++) {
curr = curr->next;
}
curr->next = curr->next->next;
return dummy.next;
}
};class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
int length = 0;
ListNode curr = head;
while (curr != null) {
length++;
curr = curr.next;
}
ListNode dummy = new ListNode(0, head);
curr = dummy;
for (int i = 0; i < length - n; i++) {
curr = curr.next;
}
curr.next = curr.next.next;
return dummy.next;
}
}def removeNthFromEnd(head: Optional[ListNode], n: int) -> Optional[ListNode]:
length = 0
curr = head
while curr:
length += 1
curr = curr.next
dummy = ListNode(0, head)
curr = dummy
for _ in range(length - n):
curr = curr.next
curr.next = curr.next.next
return dummy.nextfunc removeNthFromEnd(head *ListNode, n int) *ListNode {
length := 0
curr := head
for curr != nil {
length++
curr = curr.Next
}
dummy := &ListNode{Next: head}
curr = dummy
for i := 0; i < length-n; i++ {
curr = curr.Next
}
curr.Next = curr.Next.Next
return dummy.Next
}