type ListNode struct { Val int Next *ListNode } func removeNthFromEnd(head *ListNode, n int) *ListNode { dummy := &ListNode{0, head} first, second := dummy, dummy for i := 0; i <= n; i++ { first = first.Next } for first != nil { first = first.Next second = second.Next } second.Next = second.Next.Next return dummy.Next } // Initial list: 1 -> 2 -> 3 -> 4 -> 5 -> null // Remove 2nd from end // Print resulting list
The function uses two pointers with a gap of n nodes. When the first pointer reaches the end, the second pointer is just before the node to remove. Removing the 2nd node from the end (which is 4) results in the list: 1 -> 2 -> 3 -> 5 -> null.
type ListNode struct { Val int Next *ListNode } func removeNthFromEnd(head *ListNode, n int) *ListNode { dummy := &ListNode{0, head} first, second := dummy, dummy for i := 0; i <= n; i++ { first = first.Next } for first != nil { first = first.Next second = second.Next } second.Next = second.Next.Next return dummy.Next } // Initial list: 10 -> 20 -> 30 -> null // Remove 1st from end // Print resulting list
The last node (value 30) is removed, so the list becomes 10 -> 20 -> null.
func removeNthFromEnd(head *ListNode, n int) *ListNode { dummy := &ListNode{0, head} first, second := dummy, dummy for i := 0; i <= n; i++ { first = first.Next } for first != nil { first = first.Next second = second.Next } second.Next = second.Next.Next return dummy.Next }
If n is greater than the length of the list, the loop moving the first pointer will cause first to become nil and then accessing first.Next causes a nil pointer dereference runtime error.
The dummy node helps handle edge cases where the node to remove is the head node. It provides a stable previous node to update the next pointer.
type ListNode struct { Val int Next *ListNode } func removeNthFromEnd(head *ListNode, n int) *ListNode { dummy := &ListNode{0, head} first, second := dummy, dummy for i := 0; i <= n; i++ { first = first.Next } for first != nil { first = first.Next second = second.Next } second.Next = second.Next.Next return dummy.Next } // Initial list: 5 -> 10 -> 15 -> 20 -> 25 -> null // Remove 3rd from end twice // Print resulting list
First removal removes node with value 15 (3rd from end). List becomes 5 -> 10 -> 20 -> 25.
Second removal removes node with value 10 (3rd from end in new list). Final list: 5 -> 20 -> 25.
