题目:给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
输入:head = [1], n = 1 输出:[]
输入:head = [1,2], n = 1 输出:[1]
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
# 创建一个虚拟节点,并将其下一个指针作为链表的头部
dummy_head = ListNode(0, head)
# 创建两个指针,慢指针和快指针,并将他们初始化为虚拟节点
fast = slow = dummy_head
# 首先移动快指针,快指针给慢指针快n+1步,让快指针和慢指针之间保持一个n+1的距离
for i in range (n+1):
fast = fast.next
# 接着同时移动快指针和慢指针,当fast为空的时候,slow指针刚好在要删除的节点的前面一个
while fast:
fast = fast.next
slow = slow.next
# 结束while循环之后,说明fast的值已经为空,则通过更新slow的下一个节点来删除倒数第n的元素
# 因为slow的下一个元素就是要删除的元素,就跳过这个元素就可以达到删除的目的
slow.next = slow.next.next
# 最后返回链表的头结点
return dummy_head.next
本题思路的详细解释为:
1.准备阶段
- 创建虚拟头节点 (
dummy_head
): 这是一个常用技巧,用来简化在链表头部进行操作的逻辑,比如删除头节点自身。dummy_head
的next
指向链表的实际头节点head
。 - 初始化两个指针 (
slow
和fast
): 两个指针都开始于虚拟头节点dummy_head
。这是为了处理边界条件,特别是当需要删除的是头节点时。
2.快指针先行
- 移动快指针 (
fast
): 快指针先于慢指针移动n+1
步。这样做的目的是创建一个恰好为n+1
的窗口,使得当快指针到达链表末尾时,慢指针的下一个节点就是我们需要删除的节点。快指针先移动确保了当我们开始同时移动快慢指针时,它们之间始终保持n+1
的距离。
3.同时移动快慢指针
- 同时移动
slow
和fast
指针: 从虚拟头节点开始,快慢指针同时向前移动,直到快指针 (fast
) 到达链表的末尾(fast
成为None
)。由于快慢指针之间的距离是固定的,当快指针到达末尾时,慢指针 (slow
) 正好位于倒数第 n+1 个节点处。
4.删除目标节点
- 删除节点: 由于慢指针现在指向倒数第 n+1 个节点,它的下一个节点就是我们要删除的目标节点。通过将慢指针的
next
指向next.next
,我们就跳过了目标节点,从而实现了删除操作。
5.返回结果
- 返回修改后的链表: 由于可能删除的是头节点,我们返回
dummy_head.next
,这保证了无论删除的是不是头节点,返回的都是链表的当前头节点。
备注下图中的f1和s1表示fast和slow指针是同时进行的。
本文的对于力扣19题的单向链表中删除倒数第 n 个节点的python解答,仅仅是个人学习资料记录,也十分高兴我的见解可以帮助其他的正在做这个题目的同学,基础较差,仅仅是个人见解,大神勿喷,欢迎交流,谢谢!