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

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
- 链表中结点的数目为 sz
- 1 <= sz <= 30
- 0 <= Node.val <= 100
- 1 <= n <= sz
进阶:你能尝试使用一趟扫描实现吗?
解题思路
Go代码
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeNthFromEnd(head *ListNode, n int) *ListNode {
// 经典快慢双指针的题,快指针先走 n 步
// 随后快慢指针一起走,每次走一步,当快指针到尾的时候,慢指针指向了倒数第n个节点的前一个节点
// 注意:删除节点,一般是要找到需要删除节点的前一个节点,然后改变指向完成删除
// 而要删除的节点可能是第一个节点,所以为了统一操作,常规操作是建立一个虚拟头节点dummy
// 假设一共m个节点,则首节点走到尾节点需要m-1步,倒数第n个节点,前面还有m-n个节点,走到这第m-n个节点,
// 就是走到了倒数第n个节点的前一个节点,需要m-n-1步。所以共m-1步,快指针先走n步,后面快慢指针一起走
// 走的步数刚好就是m-n-1步,使得慢指针指向倒数第n个节点的前一节点
if head == nil {
return nil
}
dummy := &ListNode{}
dummy.Next = head
slow,fast := dummy,dummy
for i:= 0;i < n;i++ {
fast = fast.Next
}
for fast.Next != nil {
fast = fast.Next
slow = slow.Next
}
slow.Next = slow.Next.Next
return dummy.Next
}
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
// func removeNthFromEnd(head *ListNode, n int) *ListNode {
// // 方法二:删除节点,一般是要找到需要删除节点的前一个节点,然后改变指向完成删除,
// // 经验:链表操作可能要操作头节点时,一般会建立一个虚拟头节点dummy
// // 思路:计算出链表的长度m,便可以知道倒数第n个节点的前一个节点应该是顺数的第m - n个节点
// // 由于有一个dummy头节点,所以是移动 m - n 步
// m := 0
// dummy := &ListNode{}
// dummy.Next = head
// cur := dummy.Next
// for cur != nil {
// m++
// cur = cur.Next
// }
// cur = dummy
// for i := 0 ; i < m - n;i++ {
// cur = cur.Next
// }
// if cur.Next != nil {
// cur.Next = cur.Next.Next
// }
// return dummy.Next
// }

485

被折叠的 条评论
为什么被折叠?



