目录
题目
题目链接
思路
复杂度
代码
题目
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random –> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random –> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
- val:一个表示 Node.val 的整数。
- random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
你的代码 只 接受原链表的头节点 head 作为传入参数。

题目链接
138. 随机链表的复制 – 力扣(LeetCode)
https://leetcode.cn/problems/copy-list-with-random-pointer/description/?envType=study-plan-v2&envId=top-100-liked
思路
核心思想:使用哈希表建立原节点到新节点的映射。
第一次遍历:创建所有新节点,并将原节点与新节点的对应关系存入哈希表。
第二次遍历:根据原链表的连接关系,通过哈希表找到新节点对应的 next 和 random 指向的新节点,完成链接。
这种方法简单直观,且能处理 random 指向任意节点的情况(包括 null)。
复杂度
-
时间复杂度:O(n),需要遍历原链表两次,每次遍历所有节点。
-
空间复杂度:O(n),哈希表存储了 n 个节点的映射关系。
代码
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) {
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
// 如果原链表为空,直接返回空指针
if (!head) return nullptr;
// 哈希表:key 为原节点指针,value 为新创建的对应节点指针
unordered_map<Node*, Node*> nodeMap;
// 第一次遍历:创建所有新节点,并建立映射
Node* cur = head;
while (cur != nullptr) {
// 以原节点的值创建新节点,并将映射存入哈希表
nodeMap[cur] = new Node(cur->val);
cur = cur->next;
}
// 第二次遍历:连接新节点的 next 和 random 指针
cur = head;
while (cur != nullptr) {
// nodeMap[cur] 是当前原节点对应的新节点
// 新节点的 next 应指向原节点的 next 对应的新节点(通过哈希表查找)
nodeMap[cur]->next = nodeMap[cur->next];
// 新节点的 random 应指向原节点的 random 对应的新节点(若原 random 为空,则哈希表查找返回 nullptr)
nodeMap[cur]->random = nodeMap[cur->random];
cur = cur->next;
}
// 返回原链表头节点对应的新节点,即新链表的头
return nodeMap[head];
}
};





