cpp
/*
// 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:
unordered_map<Node*,Node*>cacheNode;
Node* copyRandomList(Node* head) {
Node *p = head;
while(p!=nullptr){
cacheNode[p] = new Node(p->val);
p = p->next;
}
p = head;
while(p!=nullptr){
cacheNode[p]->next = cacheNode[p->next];
cacheNode[p]->random = cacheNode[p->random];
p = p->next;
}
return cacheNode[head];
}
};
这题的方法可以精简成一句话:
先用哈希表建立"原节点 → 新节点"的映射,再根据原链表的
next和random去连接新链表。
方法流程:
// 第一遍:创建新节点
while (p != nullptr) {
cacheNode[p] = new Node(p->val);
p = p->next;
}
// 第二遍:连接 next 和 random
p = head;
while (p != nullptr) {
cacheNode[p]->next = cacheNode[p->next];
cacheNode[p]->random = cacheNode[p->random];
p = p->next;
}
核心映射关系要记住:
原节点 p -> cacheNode[p]
原 p->next -> cacheNode[p->next]
原 p->random -> cacheNode[p->random]
易错点
最容易错的是第二遍写成:
cacheNode[p]->next = p->next; // 错
cacheNode[p]->random = p->random; // 错
这样新节点又指回原链表了,不是深拷贝。
必须写:
cacheNode[p]->next = cacheNode[p->next];
cacheNode[p]->random = cacheNode[p->random];
第二个易错点是:
cacheNode[p] = new Node(p->val);
这里只复制了:
val
还没有复制 next 和 random,所以必须有第二遍连接。
第三个易错点是理解:
cacheNode[p->random]
它不是 random 本身,而是:
原 random 节点对应的新节点。
比如:
A.random -> C
那么:
cacheNode[A]->random = cacheNode[C];
得到:
A'.random -> C'
复杂度
两次遍历都是 O(n):
时间复杂度:O(n)
哈希表存了 n 个映射:
空间复杂度:O(n)
最后可以直接背这个模板:
unordered_map<Node*, Node*> map;
// 1. 创建
map[原节点] = 新节点;
// 2. 连接
map[p]->next = map[p->next];
map[p]->random = map[p->random];
// 3. 返回
return map[head];
口诀:
第一遍造节点,第二遍连关系;所有旧指针,都要通过 map 找到对应的新节点。