- 题目描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
- 示例
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
- 解决思路一
官方题解中的第二种思路。首先使用哑节点,为了简化特殊情况(链表中只有一个节点或需要删除头节点),这两种情况下如果没有哑节点,返回值是空;其次使用两个指针fast和slow,fast指针先向前移动n+1步,和slow间隔n;然后fast和slow同时向后移动,直到fast指针指向了最后一个节点null,此时slow指向的节点即为要删除的节点,就是从倒数第一个节点往前数的第n个节点,那么我们需要做的就是让slow指向它的下下个节点,即可成功删除要求的节点。
- 代码一
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
#增加哑节点
#为了防止要删除头节点或者链表中只有一个节点的情况
front = ListNode(0)
front.next,fast,slow = head,front,front
while(n or fast):
if n:
#快指针先向后移动n次
fast,n=fast.next,n-1
else:
#然后快慢指针同时向后移动,直到快指针指向链表末尾的NULL
#此时slow的下一个节点就是要删除的节点
fast = fast.next
if fast:
slow = slow.next
slow.next = slow.next.next
#返回链表的头节点
return front.next
- 解决思路二
首先遍历链表,得到链表的长度length,那么可知要删除的节点的位置是length-n(从0开始计数);然后再次遍历链表,直到要删除的节点的前一个节点(位置时length-n-1),就可以删除节点了,最终要返回的就是删除节点后的链表,在这里要考虑的特殊情况是如果要删除的节点是头节点,那么length-n就是0,在第二次遍历时,length-n-1是取不到的,无法删除,所以要另外讨论。
- 代码二
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
length = 0 #链表长度
p = head #临时指针
while p:
p = p.next
length += 1
idx = length - n #要删除的节点位置(从0开始数)
p = head #重新赋值临时指针
if idx == 0: #如果要删除的指针是头指针
return head.next
for i in range(length):
if i == idx-1: #找到要删除节点的前一个节点
p.next = p.next.next
return head
else:
p = p.next #没遍历到该位置时,保持向后移动