24. 两两交换链表中的节点——双指针,好题!

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

进阶:你能尝试使用一趟扫描实现吗?

双指针法

这个算法用于 删除链表的倒数第 n 个节点,并返回删除后的链表头节点。核心思路是 快慢指针

  1. 虚拟头节点(pre_head

    • 创建一个虚拟头节点 pre_head,它的 next 指向真正的头节点 head

    • 这样可以避免单独处理头节点的删除(比如 n = 链表长度 时删除头节点)。

  2. 快慢指针初始化

    • fast 和 slow 都从 pre_head 开始。

  3. 快指针先走 n 步

    • fast 先向前移动 n 步,使得 fast 和 slow 之间相隔 n 个节点。

    • 这样当 fast 到达链表末尾时,slow 正好指向倒数第 n+1 个节点(即要删除节点的前驱)。

  4. 快慢指针同步移动

    • 同时移动 fast 和 slow,直到 fast 到达最后一个节点(fast.next 为 None)。

    • 此时 slow 指向倒数第 n+1 个节点。

  5. 删除目标节点

    • slow.next = slow.next.next,跳过倒数第 n 个节点,完成删除。

  6. 返回新链表头

    • 返回 pre_head.next,因为 pre_head 始终指向真正的头节点。

示例

假设链表为 1 → 2 → 3 → 4 → 5n = 2(删除倒数第 2 个节点 4):

  1. 初始化pre_head → 1 → 2 → 3 → 4 → 5fast = slow = pre_head

  2. 快指针先走 2 步

    • fast 移动到 1(第 1 步)。

    • fast 移动到 2(第 2 步)。

  3. 快慢指针同步移动

    • fast 移动到 3slow 移动到 1

    • fast 移动到 4slow 移动到 2

    • fast 移动到 5slow 移动到 3(此时 fast.next 为 None,停止)。

  4. 删除 slow.next(即 4

    • slow.next = slow.next.next3.next 指向 5)。

  5. 最终链表1 → 2 → 3 → 5

时间复杂度

  • O(n),只需遍历链表一次。

空间复杂度

  • O(1),只用了几个指针变量,没有额外空间。

关键点

  • 虚拟头节点 简化边界情况(如删除头节点)。

  • 快指针先走 n 步,确保 slow 最终指向倒数第 n+1 个节点。

  • 同步移动快慢指针,直到 fast 到达末尾。

这样就能高效删除倒数第 n 个节点! 🚀

 

# 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]:
        pre_head = ListNode()
        pre_head.next = head
        fast = slow = pre_head
        for _ in range(n):
            fast = fast.next
        while fast.next: # 直到fast到达尾节点停止
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next
        return pre_head.next

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值