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
        
相关推荐
WZ188104638692 分钟前
LeetCode第54题
算法·leetcode
丰海洋13 分钟前
Leetcode-hot100-136只出现一次的数字
算法·leetcode·职场和发展
We་ct17 分钟前
LeetCode 124. 二叉树中的最大路径和:刷题解析
前端·数据结构·算法·leetcode·typescript
追随者永远是胜利者8 小时前
(LeetCode-Hot100)253. 会议室 II
java·算法·leetcode·go
程序员酥皮蛋9 小时前
hot 100 第三十五题 35.二叉树的中序遍历
数据结构·算法·leetcode
追随者永远是胜利者9 小时前
(LeetCode-Hot100)207. 课程表
java·算法·leetcode·go
望舒51313 小时前
代码随想录day33,动态规划part2
java·算法·leetcode·动态规划
追随者永远是胜利者14 小时前
(LeetCode-Hot100)169. 多数元素
java·算法·leetcode·go
Navigator_Z18 小时前
LeetCode //C - 962. Maximum Width Ramp
c语言·算法·leetcode
兩尛18 小时前
409. 最长回文串
c++·算法·leetcode