leetcode hot100 19.删除链表的倒数第 N 个结点 快慢指针 medium


核心思路:制造"距离差"

要删除倒数第 nnn 个节点,需要找到它的前驱节点(即倒数第 n+1n+1n+1 个)。

  • 让 fast 指针先向前走 n+1n+1n+1 步。此时,fast (指向第n+1个节点)和 slow (指向第一个节点)之间隔了 nnn 个节点。
  • 同时移动 fast 和 slow,直到 fast 指向最后一个节点。此时 slow 恰好指向倒数第 n+1n+1n+1 个节点

这道题不需要创建新链表,所以不是:

python 复制代码
        prehead = ListNode(-1)
        dummy = prehead
	
			... ...

            # 建立新节点并移动指针
            dummy.next = ... ...
            dummy = dummy.next

重组旧链表,只需要新建一个 prehead 节点,指向链表

python 复制代码
        prehead = ListNode(-1)
        prehead.next = head  
        ... ...

		return prehead.next

直接返回head不行吗,为什么要prehead = ListNode(-1)

prehead.next = head 返回prehead.next:
核心原因:头节点也是会被删除的

假设链表是 1, 2,要删除倒数第 2 个(也就是删除 1):

  1. prehead 指向 1。
  2. 经过计算,slow 停在 prehead 上。
  3. 执行 slow.next = slow.next.next(即 prehead.next = 2)。
  4. 此时:head 变量依然指向 1。prehead.next 指向 2。

如果 return head,结果是 1, 2(错误); 如果 return prehead.next,结果是 2(正确)

"哑节点" (Dummy Node) 的作用

  • 防止"丢头":如上所述,处理头节点被删除的情况。、、
  • 空链表保护:当链表被删空时,prehead.next 会正确返回 None,而直接操作 head 可能会导致空指针引用报错

时间复杂度 :O(N)O(N)O(N)

虽然有两个循环(for 和 while),但指针一共只从头走到尾一次。
空间复杂度:O(1)O(1)O(1)

只额外申请了 prehead, fast, slow 这几个引用空间。

python 复制代码
# 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]:

        # 用于指向新链表
        prehead = ListNode(-1)
        prehead.next = head  # 这一步是修复报错的关键

        # 用于操作旧链表
        fast = slow = prehead
        
        # fast先走n+1步
        for i in range(n+1):
            fast = fast.next

        # 同时移动 fast 和 slow,直到 fast 指向最后一个节点
        # 此时 slow 恰好指向倒数第 n+1 个节点
        while fast:
            slow = slow.next
            fast = fast.next

        # 倒数第 n+1 个节点,应该指向:倒数第 n+2 个节点
        #(跳过倒数n)
        tmp = slow.next.next
        slow.next = tmp

        return prehead.next
        
相关推荐
To_OC3 小时前
LC 51 N 皇后:我以为难的是回溯,结果栽在了对角线下标
javascript·算法·leetcode
闪电悠米15 小时前
力扣hot100-73.矩阵置零-标记数组详解
算法·leetcode·矩阵
过期动态18 小时前
【LeetCode 热题 100】找到字符串中所有字母异位词
java·数据结构·算法·leetcode·职场和发展·rabbitmq
Adios7941 天前
设置交集大小至少为2
数据结构·算法·leetcode
程序猿乐锅1 天前
【数据结构与算法 | 第六篇】力扣1109,1094差分数组
java·算法·leetcode
hold?fish:palm2 天前
9 找到字符串中所有字母异位词
c++·算法·leetcode
Sw1zzle2 天前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木2 天前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
啦啦啦啦啦zzzz2 天前
算法:回溯算法
c++·算法·leetcode
小肝一下2 天前
3. 单链表
c语言·数据结构·c++·算法·leetcode·链表·dijkstra