第4章|链表

Unit 00 · 链表、指针与可达性基础

仅本次页面有效
U00
Linked List FundamentalsIdentity · Edge · Reachability · Mutation

链表不是“会移动的数组”,
而是一组节点与引用关系。

真正发生变化的不是节点在画布上的位置,而是节点字段中保存的引用。本单元先建立节点身份、指针、边、可达性和现场保存,再预览后续所有常见链表概念。

已恢复上次学习位置阶段、动画、答题和代码内容已从本浏览器恢复。

本单元要先建立的底层认知

  • 区分节点的值、节点对象、指针变量和 next 边;
  • 理解从 head 出发的可达性,识别失联节点与意外环;
  • 掌握“先保存后继,再改边,再移动指针”的安全修改顺序;
  • 提前认识 dummy、pre/cur/next、fast/slow、tail、random 与双向链表。

贯穿本章的安全改链模板

next_node = current.next # 先保住未处理入口 current.next = ... # 再修改结构 current = next_node # 最后移动工作指针 每步都要问:head 还能到达哪些节点?
Node Identity

节点身份是对象本身。两个节点即使 value 相同,也可能是完全不同的节点。

Pointer Variable

head、current 等变量只保存节点引用。移动变量不等于改变链表结构。

Edge / next

修改 node.next 才会改变链表的有向连接;动画必须表现边变化,而非节点交换位置。

Reachability

从返回入口沿 next 能访问到的节点才属于当前结果链。失去所有入口的节点会失联。

CHAPTER 04 / THE COGNITIVE ATLAS

第 4 章 · 认知梯度全景图

链表:看清节点之间的连接,练习指针操作与局部改写。

13 个后续单元
贯穿本章的统一框架确定入口与前驱 → 保存后继 → 移动或重连 → 检查可达性。节点身份与节点值必须分开。

从基础到复合任务,每一步增加一种决策

这里的梯度描述认知任务的递进,不等同于题库的难度标签。点击题目可进入对应单元。

起点 · Unit 00 链表、指针与可达性。先理解状态、操作与不变量,再沿下列路线练习。
  1. 01

    安全重连

    从删除一条边到反转整个后缀,再处理局部边界。

  2. 02
  3. 03

    结果构造

    把有序前沿与进位状态接入结果链,明确输入与输出入口。

  4. 04

    身份与复合结构

    从引用翻译到哈希与双向链表同步维护。

每道题在框架中的具体形式

用同一组问题定位每个单元,再观察迁移题改变了哪个条件。进入写代码环节后,学习地图会收起,留出独立思考的空间。

UNIT 01安全重连

#203 移除链表元素

指针角色
虚拟头节点固定入口,前驱指向下一个待判断节点之前。
移动或重连
命中删除条件时绕过后继;保留时才推进前驱。
可达性不变量
前驱之前均已处理,剩余节点从前驱后继保持可达。
边界检查
连续删除和删除头节点使用相同逻辑。
迁移 · #83 删除排序链表中的重复元素有序链表去重把删除条件改为相邻节点值相同。
先说清契约,再独立实现进入本单元 ↗
UNIT 02安全重连

#206 反转链表

指针角色
已反转区头、未处理区头与预先保存的原后继。
移动或重连
先保存原后继,再反向连接当前边,最后推进两区入口。
可达性不变量
两区不重叠且覆盖全部原节点,未处理入口不能丢失。
边界检查
空链和单节点;改变指向前必须保留未来路径。
迁移 · #234 回文链表回文链表组合找中点、反转后半段与逐对比较,并考虑恢复结构。
先说清契约,再独立实现进入本单元 ↗
UNIT 03安全重连

#92 反转链表 II

指针角色
反转区之前的节点、当前区间头与固定区间尾。
移动或重连
把下一个节点移到区间头,保留区间外连接。
可达性不变量
外部入口仍指向反转区头,原区间头逐渐成为尾。
边界检查
左端为头节点、左右端相同与右端为尾节点。
迁移 · #24 两两交换链表中的节点两两交换把可变反转区改为固定两节点的局部重写。
先说清契约,再独立实现进入本单元 ↗
UNIT 04安全重连

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

指针角色
前驱、第一节点、第二节点与组后入口。
移动或重连
确认整组存在,再把前驱接到第二、第二接到第一、第一接到组后。
可达性不变量
已完成区与未处理区保持相连,节点身份不变。
边界检查
奇数个节点时保留最后一个节点。
迁移 · #25 K 个一组翻转链表K 组反转先检查剩余节点是否够一组,再整体反转与接回。
先说清契约,再独立实现进入本单元 ↗
UNIT 05距离与速度

#19 删除链表的倒数第 N 个结点

指针角色
虚拟头节点上的快慢指针,间距用于定位目标前驱。
移动或重连
先建立 n+1 条边的间距,再同步移动直到快指针离开链表。
可达性不变量
同步阶段间距固定,结束时慢指针后继是待删除节点。
边界检查
删除头节点依赖 dummy;不同终止条件不能混用间距。
迁移 · #2095 删除链表的中间节点删除中间节点把固定间距换成倍速定位,仍需找到前驱。
先说清契约,再独立实现进入本单元 ↗
UNIT 06距离与速度

#876 链表的中间结点

指针角色
慢指针走一步,快指针走两步。
移动或重连
快指针抵达末端时,慢指针定位中点。
可达性不变量
每轮结束时快指针走过的距离是慢指针的两倍。
边界检查
偶数长度返回哪个中点由初始位置与循环条件决定。
迁移 · #143 重排链表重排链表还要断开、反转后半段,再交错合并。
先说清契约,再独立实现进入本单元 ↗
UNIT 07距离与速度

#141 环形链表

指针角色
沿同一后继关系运动的两个不同速度指针。
移动或重连
只读移动;若有环,进入环后通过相对速度逐步缩小位置差。
可达性不变量
比较的是节点身份,相同值不代表相遇。
边界检查
快指针与其后继均须存在才能继续。
迁移 · #202 快乐数快乐数把 next 换成数位平方和,检测确定性状态转换的循环。
先说清契约,再独立实现进入本单元 ↗
UNIT 08距离与速度

#142 环形链表 II

指针角色
第一阶段的相遇点与第二阶段从链头出发的定位指针。
移动或重连
先倍速判圈,再从链头与相遇点同速前进。
可达性不变量
第二阶段两个指针最终在环入口对齐。
边界检查
无环返回空结果;相遇点通常不是入口。
迁移 · #287 寻找重复数寻找重复数把数组下标当节点、数组值当后继,复用入口定位。
先说清契约,再独立实现进入本单元 ↗
UNIT 09距离与速度

#160 相交链表

指针角色
分别走 A 后 B、B 后 A 的两个指针。
移动或重连
走到空节点时切换另一条链头,抵消独有前缀长度差。
可达性不变量
两指针经过相同轮数,最多走相同的拼接总路程。
边界检查
比较节点对象;无交点时最终同时到达空节点。
迁移 · #1650 二叉树的最近公共祖先 III带 parent 的最近公共祖先把 next 换成父引用,仍使用路径对齐。
先说清契约,再独立实现进入本单元 ↗
UNIT 10结果构造

#21 合并两个有序链表

指针角色
两条有序链的未处理头与结果尾指针。
移动或重连
比较两侧最小前沿,把较小节点接到结果尾,再推进该侧。
可达性不变量
结果前缀有序,两个剩余入口都保持可达。
边界检查
一侧耗尽后直接接上另一侧,保留原节点身份。
迁移 · #23 合并 K 个升序链表K 路合并用最小堆代替两路直接比较,维护每一路的当前前沿。
先说清契约,再独立实现进入本单元 ↗
UNIT 11结果构造

#2 两数相加

指针角色
两输入当前位置、进位、虚拟头与结果尾。
移动或重连
从低位同步累加,输出当前位并携带下一位进位。
可达性不变量
结果已写低位正确,carry 是对未处理高位的唯一影响。
边界检查
长度不同与最后一位额外进位,循环不能只检查输入。
迁移 · #445 两数相加 II正序存储先用栈取得低位,再从结果头部构造。
先说清契约,再独立实现进入本单元 ↗
UNIT 12身份与复合结构

#138 随机链表的复制

指针角色
原节点身份到新节点身份的映射。
移动或重连
先创建每个副本,再把 next 与 random 翻译为副本引用。
可达性不变量
每个原节点只对应一个副本,副本引用不指回原对象。
边界检查
空引用、自引用与多个节点共享同一随机目标。
迁移 · #133 克隆图克隆图改用遍历发现节点,并翻译全部邻接引用。
先说清契约,再独立实现进入本单元 ↗
UNIT 13身份与复合结构

#146 LRU 缓存

指针角色
键到节点的哈希表与按最近使用程度排列的双向链表。
移动或重连
读写命中移到最近端,满容量时淘汰最久未使用节点。
可达性不变量
表与链中的业务节点一一对应,双向边始终互相一致。
边界检查
更新已有键不增加容量;淘汰时同步删除表项。
迁移 · #460 LFU 缓存LFU 增加频率桶和最小频率,同频率内部仍按最近使用顺序。
先说清契约,再独立实现进入本单元 ↗
认知任务 1
先区分“值相同”和“节点相同”
画面中有两个值都为 7 的节点。请根据节点 ID 和指针指向判断它们是否是同一个对象。
链表结构实验台状态 0 / 4
从 head 可达区域
失联风险区
本步断开的边无
本步新建的边无
观察状态
保存引用
断开旧边
建立新边
验证可达
两个值为 7 的节点分别是 n1 与 n2。值相同不能推出对象相同。
安全反转微型模板补全不是背答案,而是保持未处理入口
def reverse_demo(head): previous = None current = head while current: next_node = current.next = previous previous = current current = return
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


def reverse_demo(head):
    previous = None
    current = head

    while current:
        next_node = current.next
        current.next = previous
        previous = current
        current = next_node

    return previous
代码—指针—边逐行联动1 / 15
previousNone
currentn1
next_node—
从返回候选可达[]
进入函数,尚未修改任何连接。

Unit 00 Skill:先保护可达性,再修改连接

面对链表题时,先画出节点身份和当前边;明确返回入口与未处理入口;在覆盖 next 前保存仍需访问的引用;改边后重新检查从入口可达的节点、是否失联以及是否成环。

触发信号题目要求删除、插入、交换、反转或重排节点
核心表示节点对象 + 指针变量 + next 边 + 返回入口
安全顺序Save → Disconnect → Connect → Move → Verify
身份判断节点相同看对象引用,不看 value 是否相等
结构检查从 head 遍历可达集合,并检测重复访问形成的环
下一单元dummy 如何统一删除头节点与中间节点
学习完成后不会自动跳转

页面会停留在这里。你可以继续复习任意阶段,或在准备好之后手动打开 Unit 01。刷新页面也会回到当前进度。

手动进入 Unit 01 →
进度已保存