一,题目
给你一个长度为 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
作为传入参数。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]] 输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
二,解题思路
创建一个哈希表,两次遍历链表。
-
创建哈希映射:使用
unordered_map
hmap
来存储原链表节点和新链表节点之间的映射关系。 -
复制每个节点的值:第一个
while
循环遍历原链表,为每个节点创建一个新的节点,并将其插入到hmap
中。新节点的值与原节点的值相同,next
和random
指针初始化为nullptr
。cpp
Node *p = head; while (p) { hmap.insert({p, new Node(p->val)}); p = p->next; }
-
复制
next
和random
指针:第二个while
循环再次遍历原链表,使用hmap
来设置新节点的next
和random
指针。对于每个节点,新节点的next
指针指向原节点next
所指向的新节点,新节点的random
指针指向原节点random
所指向的新节点。cpp
p = head; while (p) { hmap[p]->next = hmap[p->next]; hmap[p]->random = hmap[p->random]; p = p->next; }
-
返回新链表的头节点:最后,函数返回新链表的头节点,即
hmap[head]
。cpp
return hmap[head];
这个函数的关键在于使用 unordered_map
来存储原节点和新节点之间的映射关系,这样在复制 next
和 random
指针时可以轻松地引用对应的新节点。
请注意,这段代码假设 Node
结构体定义如下:
cpp复制
struct Node {
int val;
Node *next;
Node *random;
Node(int x) : val(x), next(nullptr), random(nullptr) {}
};
这个 Node
结构体包含一个整数值 val
,两个指针 next
和 random
,以及一个构造函数来初始化节点。在实际应用中,你需要确保适当地管理内存,避免内存泄漏。
三,代码实现
class Solution {
public:
Node* copyRandomList(Node* head) {
unordered_map<Node*, Node*> hmap;
Node* p = head;
while(p)
{
hmap.insert({p, new Node(p->val)});
p = p->next;
}
p = head;
while(p)
{
hmap[p]->next = hmap[p->next];
hmap[p]->random = hmap[p->random];
p = p->next;
}
return hmap[head];
}
};