题目描述#

给你一个链表的头节点 head,要求删除链表的倒数第 n 个节点,并返回删除后的链表头节点。

这道题的关键不在于找到节点的值,而在于真正把目标节点从链表里摘掉,所以最后需要调整前后节点的指针连接关系。

思路#

这份代码使用的是链表里很经典的双指针做法。先创建一个哑节点 dummy 指向原链表头部,这样即使要删除的是原来的第一个节点,也可以统一按“删除某个节点的前一个节点后面那个节点”的方式处理,不需要单独分类讨论。

接下来让 slowfast 都从 dummy 出发,但先让 fast 多走 n+1 步。这样做之后,fastslow 之间就始终隔着 n 个节点。后面再让两个指针一起往后走,直到 fast 走到 nil,此时 slow 正好停在“倒数第 n 个节点”的前一个位置。

既然 slow 已经来到了目标节点的前驱,那么删除操作就很直接了,只需要执行 slow.Next = slow.Next.Next,把目标节点从链表中跳过去即可。

整个过程只遍历链表一次,时间复杂度是 O(n),额外只用了几个指针变量,空间复杂度是 O(1)

代码#

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeNthFromEnd(head *ListNode, n int) *ListNode {
	dummy := &ListNode{Next: head}
	slow := dummy
	fast := dummy
	// 让fast指针先走n+1步
	for i := 0; i <= n; i++ {
		fast = fast.Next
	}
	for fast != nil {
		fast = fast.Next
		slow = slow.Next
	}
	slow.Next = slow.Next.Next
	return dummy.Next
}
本站总访问量  ·  访客数
你的IP 获取中…