第4章|链表

Unit 03 · LeetCode #92 反转链表 II

← Unit 02
仅本次页面有效
U03
Reverse Linked List IIBoundary · Detach · Insert · Reconnect

局部反转不是把 Unit 02 再做一次,
而是反转过程中还要守住区间两侧。

完整反转只需维护“已反转区”和“未处理区”。局部反转还多出左侧固定前缀与右侧未动后缀;任何一次改边都必须保证它们仍能接回结果链。

已恢复上次学习位置阶段、动画、代码、迁移脚手架和滚动位置已恢复。
LeetCode #92 题目模型Reverse Linked List II · Medium

题目要求

给定单链表头节点 head 和两个整数 left、right,反转位置从 left 到 right 的节点,并返回修改后的链表。

# ListNode 由 LeetCode 预定义 class Solution: def reverseBetween( self, head: Optional[ListNode], left: int, right: int ) -> Optional[ListNode]: pass

输入、输出与约束

  • 节点数 1 ≤ n ≤ 500,节点值在 [-500, 500]。
  • 1 ≤ left ≤ right ≤ n。
  • 进阶目标:一趟扫描完成,时间 O(n),额外空间 O(1)。

示例

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
输入:head = [5], left = 1, right = 1
输出:[5]

本页主方法

使用 dummy + before + current + moving 的区间头插法。每次把 current 后面的一个节点摘下,插到 before 后面。

先连接上一题:#206 的三指针 Skill 仍在,但目标从“反转全部边”变为“移动局部节点”

Unit 02:完整反转

current.next = previous
每轮改变当前节点出边方向,最后返回 previous。

→
Unit 03:局部头插

moving = current.next
摘下 moving,插到 before 后;current 始终是区间尾。

dummy

稳定的虚拟前驱。即使 left=1,反转区间前仍然存在 before,避免单独处理头节点。

before

反转区间前一个节点。整个头插过程保持不动,before.next 始终指向当前区间头。

current

原区间第一个节点。头插过程中它不前移,而是逐渐成为当前已反转区间的尾节点。

moving

current.next 指向的节点。本轮先把它从原位置摘下,再插到 before 后面。

认知任务 1
区分完整反转与局部反转新增的边界责任
局部反转完成后,左侧前缀、反转区间和右侧后缀必须重新组成一条从 head 可达的链。
局部反转与指针动画状态 1 / 1
固定前缀正在反转区间已形成的新区间顺序固定后缀
本步断开 / 覆盖—
本步建立 / 保存—
定位 before
保存 moving
摘下 moving
接到区间头
更新 before.next
点击下一步,观察局部反转比完整反转多维护了哪些连接。
错误实验室错误不是“结果不漂亮”,而是边界契约被破坏
没有 dummy

left=1 时找不到稳定前驱,必须额外修改 head,代码边界分支膨胀。

current 每轮前移

current 应保持为当前区间尾;前移会跳过尚未搬到区间头的节点。

多做一次头插

需要移动 right-left 个节点。多一次会把区间外的第一个节点也拖入反转区。

关键表达式补全只填写决定边界与改边顺序的部分
from typing import Optional class Solution: def reverseBetween(self, head, left, right): dummy = before = dummy for _ in range(): before = before.next current = for _ in range(): moving = current.next = moving.next = before.next = moving return
代码—链表逐行联动状态 1 / 1

当前执行状态

代码行1
before / current—
moving—
链表顺序[1,2,3,4,5]
已完成头插0
进入函数。
完成代码联动后进入 LeetCode #24 官方原题迁移代码补全正确,或播放完整轨迹后解锁;查看提示与填入骨架不会解锁。

迁移题:LeetCode #24 两两交换链表中的节点

#92 教会我们在局部范围内安全地“摘下后继并插到前面”。#24 把区间长度固定为 2,并要求对整条链表重复执行这一局部重连。迁移重点是:保留改边结构,同时重新定义循环边界和前驱移动规则。

Unit 02 → Unit 03 → #24

完整反转:逐条改变边方向;局部反转:守住区间两侧并连续头插;两两交换:把长度为 2 的局部头插重复应用到整条链表。

LeetCode #24|两两交换链表中的节点

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表头节点。不能修改节点内部的值,必须真正改变节点之间的连接关系。

from typing import Optional class Solution: def swapPairs( self, head: Optional[ListNode] ) -> Optional[ListNode]: pass
打开 LeetCode 官方原题 ↗

官方示例与约束

输入:head = [1,2,3,4]
输出:[2,1,4,3]
输入:head = []
输出:[]
输入:head = [1]
输出:[1]
输入:head = [1,2,3]
输出:[2,1,3]
  • 节点数在 [0,100] 范围内。
  • 0 ≤ Node.val ≤ 100。
  • 最后只剩一个节点时,它保持原位置。
读题检查 1:允许交换节点值吗?
先根据题面区分“交换值”与“交换节点”。
读题检查 2:输入 [1,2,3] 的结果是什么?
注意最后一个节点没有搭档。
完成两道读题检查后进入结构对照。

#92 与 #24:同一个局部改边模板,不同的调度方式

维度#92 反转链表 II#24 两两交换
处理范围只处理位置 [left,right]从头到尾处理每一对相邻节点
稳定前驱before 固定在整个反转区间前previous 每交换一对后移动到该对尾部
局部角色current 是区间尾,moving=current.nextfirst=previous.next,second=first.next
改边核心摘下 moving,插到 before 后摘下 second,插到 previous 后
循环边界固定执行 right-left 次只要还存在完整的一对就继续
尾部处理区间右侧始终由 current.next 接回奇数长度时最后一个节点保持原位
局部同构:把 #92 的一次头插限制在两个节点上:before→current→moving→following 经过重连变为 before→moving→current→following。在 #24 中只需重命名为 previous→first→second→following。
结构检查:交换完成后 previous 移到哪里?
找到交换后这一对的尾节点。
循环检查:为什么需要两个非空条件?
只有完整的一对才能交换。

把旧结构映射成 #24 的四个语义槽位

槽位 1|稳定入口与前驱

创建 dummy,并让 previous 从 dummy 开始。

等待填写。
槽位 2|识别当前一对

从 previous 后面取得 first 与 second。

等待填写。
槽位 3|安全重连三条边

先保存 following,再构造 previous→second→first→following。

等待填写。
槽位 4|移动与返回

previous 移到这一对的尾部,最后返回真实头节点。

等待填写。
四个槽位已经组成完整算法

官方样例轨迹:head = [1,2,3,4]

previous / first / second—
following—
当前链表[1,2,3,4]
已完成交换0 / 2
dummy 指向原 head,previous 从 dummy 开始。
独立重写

不要复制左侧轨迹。独立写出迭代解法,检查器只验证关键结构。

先走完官方样例,再完成独立重写。
状态 1 / 9

Unit 03 Skill 卡

触发信号:只反转链表中的连续区间。核心表示:dummy / before / current / moving。核心不变量:before.next 是区间头,current 是区间尾。核心操作:摘下 current.next,插到 before 后。复杂度:O(n) 时间、O(1) 额外空间。

与上一题联系仍然先保存将被覆盖的后继引用
新增难点守住区间左、右两侧连接
循环次数right - left 次头插
常见错误current 前移、多插一次、漏 dummy
可迁移题型两两交换、K 组翻转
推荐下一题LeetCode #24 两两交换链表
本页不会自动跳转

完成后可以停留、回看任意阶段;只有你主动点击时才进入 Unit 04。

手动进入 Unit 04 →
阶段 1 / 6 · 仅本次页面有效,可随时返回