题目核心剖析
在链表的算法考察中,带随机指针的链表复制绝对是高频考点。LeetCode 138 题虽被标注为中等难度,但实则是锻炼链表操作思维的经典题目。普通链表的复制仅需遍历处理 next 指针即可,而带 random 随机指针的链表,因 random 可指向链表任意节点(或空),复刻其指向关系成为解题核心难点。
题目要求
给定一个单链表,每个节点除了包含一个 next 指针指向下一个节点,还包含一个 random 指针,该指针可以随机指向链表中的任意一个节点,也可以指向 NULL。要求完整复制出这个链表的深拷贝,新链表的每个节点都是全新的节点,且 next 和 random 指针的指向关系与原链表完全一致。
解题难点
普通链表复制的核心是按序遍历处理 next 指针,而本题的关键痛点在于:原节点的 random 指针指向的位置是随机的,复制节点无法直接确定自己的 random 指针该指向哪个新节点。如果先单独复制所有节点再处理 random 指针,需要额外的哈希表存储原节点与复制节点的映射关系。本文分享的三步法无需额外空间(空间复杂度 O(1)),是更优的解法。
节点结构定义(C++)
首先定义题目中的链表节点结构,这是代码实现的基础:
struct Node {
int val;
Node* next;
Node* random;
Node(int x) : val(x), next(NULL), random(NULL) {}
};
核心解题思路:三步法原地复制
本次解题的核心思路是原地插入复制节点→修正复制节点的 random 指针→拆分原链表与复制链表,全程在原链表上操作,无需额外的哈希表存储映射,时间复杂度 O(n),空间复杂度 O(1)(仅使用常数个指针变量)。
为了更直观理解算法步骤,我们以原链表 1 → 2 → 3 → NULL 为例,其中原节点 1 的 random 指向 3,原节点 2 的 random 指向 1,原节点 3 的 random 指向 NULL,通过图形一步步拆解算法执行过程。
第一步:原地插入复制节点
核心操作:遍历原链表,在每个原节点的后面插入一个值相同、random 指针暂时与原节点一致的复制节点,使原链表变为 原节点→复制节点→原节点→复制节点 的成对结构。
操作目的:让复制节点与原节点形成一一对应的紧邻关系,为后续修正 random 指针提供便利。通过'原节点的 random 指向→原节点 random 的下一个节点',即可找到复制节点的正确 random 指向。
图形演示
原链表:
1 → 2 → 3 → NULL
| | |
v v v
3 1 NULL
插入复制节点后(复制节点标为 1'、2'、3'):
1 → 1' → 2 → 2' → 3 → ' →
v v v v v v


