请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:
输入:head = [[1,1],[2,1]] 输出:[[1,1],[2,1]]
示例 3:
输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例 4:
输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
提示:
-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。
第一次见到这种题,算是学习了。总的来说两种方法,一种是映射方法,一种是嗯复制方法。
1.映射(哈希):每个原链表的结点都建立一个复制结点作为映射,那么每个复制结点的next就是,原链表结点的next的映射,若用h表示映射关系,即,h(node)->next = h(node->next),random同理。
/*
// 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) {
map<Node*, Node*> m;
for (Node* cur = head; cur != nullptr; cur = cur->next) {
m[cur] = new Node(cur->val);
}
for (Node* cur = head; cur != nullptr; cur = cur->next) {
m[cur]->next = m[cur->next];
m[cur]->random = m[cur->random];
}
return m[head];
}
};
2.deepcopy方法:在原链表中,每个结点的后面复制一个相同的结点,即变为L = n1 -> n1copy -> n2 -> n2copy -> ... -> NULL。然后再处理复制结点的random,也就是 n1copy->random = n1->random->next。最后将2条链表分开。
/*
// 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 == nullptr) return nullptr;
Node* newHead = nullptr;
for (Node* cur = head; cur != nullptr; cur = cur->next->next) {
newHead = new Node(cur->val);
newHead->next = cur->next;
cur->next = newHead;
}
for (Node* cur = head; cur != nullptr; cur = cur->next->next) {
newHead = cur->next;
if (cur->random == nullptr) newHead->random = nullptr;
else newHead->random = cur->random->next;
}
Node* ans = head->next;
for (Node* cur = head; cur != nullptr; cur = cur->next) {
Node* tmp = cur->next;
if (tmp->next == nullptr) {
cur->next = nullptr;
continue;
}
cur->next = tmp->next;
tmp->next = tmp->next->next;
}
return ans;
}
};