19. 删除链表的倒数第 N 个结点
题目
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例

输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
解题思路
对于单链表的删除操作,如果想要做删除链表的倒数第n个结点,则需要找到倒数第n+1个结点的位置。而由于链表只能单向访问,因此,处理这个问题的基本方法是双指针。
令指针p1先遍历n+1步,然后,指针p2再开始与p1同时遍历,直到p1指向nil为止,然后删除p2.Next就可以了。
然而这里有一种特殊情况,就是删除的结点为头节点,此时链表的头节点会改变。为了处理这个问题,有两种办法:
- 判断被删除的结点是否是头节点,如果是头节点,则修改返回结果
添加一个桩结点,结果返回桩结点的Next指针。
事实证明,方法2是更简单的,也是更通用的。
最后给出我们的实现代码:
type ListNode struct {
Val int
Next *ListNode
}
func removeNthFromEnd(head *ListNode, n int) *ListNode {
if head == nil {
return nil
}
vNode := ListNode{Next: head}
h1 := &vNode
h2 := &vNode
// 第一个指针向前遍历n+1个位置
for i := 0; i < n+1; i++ {
if h1 == nil {
return nil
}
h1 = h1.Next
}
// 然后双指针同时遍历
for h1 != nil {
h1 = h1.Next
h2 = h2.Next
}
// 删除第n个结点
h2.Next = h2.Next.Next
// 返回结果
return vNode.Next
}