7. [code] 复制带随机指针的链表
7.1 题目
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深拷贝。
示例:
输入:
{“KaTeX parse error: Expected '}', got 'EOF' at end of input: …":"1","next":{"id”:“2”,“next”:null,“random”:{“KaTeX parse error: Expected 'EOF', got '}' at position 9: ref":"2"}̲,"val":2},"rand…ref”:“2”},“val”:1}
解释:
节点 1 的值是 1,它的下一个指针和随机指针都指向节点 2 。
节点 2 的值是 2,它的下一个指针指向 null,随机指针指向它自己。
提示:
你必须返回给定头的拷贝作为对克隆列表的引用。
难度:中等
7.2. 思路
假定上述的带随机指针的链表的类型称为Node类。
定义如下,包含值val,指向下一节点的指针next,和随机指针random.
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node() {}
Node(int _val, Node* _next, Node* _random) {
val = _val;
next = _next;
random = _random;
}
};
*/
需要2个map,一个储存原Node链表的每个节点的地址和序号,另一个存储新Node链表的每个节点的地址和序号;由于新Node链表是原链表的拷贝,这里的序号的相同的,因此,第二的map可以用vector代替。
先创建一个新Node链表,则可以将这一新链表的每个节点的地址push入上述的vector,即这一vector储存了新Node链表的每个节点地址;
再遍历原Node链表,将原Node链表的每个节点的地址和序号分别储存入map的KEY和VALUE;
对新的Node链表需要两个操作:
- 每个节点next指针相连;
- 每个节点,如果存在ranndom,则random的指向;
7.3. 代码
class Solution {
public:
Node* copyRandomList(Node* head) {
if (!head) return NULL;
//定义<Node*, int>类型的map和<Node*>类型的vector
std::map<Node*, int> node_map;
std::vector<Node*> node_vec;
//新链表的每个节点的地址push入上述的vector
Node* ptr = head;
int i=0;
while(ptr){
//vector存入新Node链表的地址
node_vec.push_back(new Node(ptr->val));
//map存入原Node链表的地址和序号
node_map[ptr]=i;
//下一个节点
ptr = ptr->next;
i++;
}
//将0加入node_vec的最末,确保后续node_vec最后一个节点的next指针指向不出错
node_vec.push_back(0);
//遍历原Node链表,
ptr = head;
i=0;
while(ptr){
//每个节点next指针相连
node_vec[i]->next = node_vec[i+1];
//每个节点,如果存在ranndom,则random的指向
if (ptr->random){
int id = node_map[ptr->random]; //该节点random指向的节点的序号
node_vec[i]->random = node_vec[id];
}
ptr = ptr->next;
i++;
}
return node_vec[0];
}
};
提交到oj上有错误
下面这个方法简直神仙方法,太棒了:
先写一下代码
class Solution{
public:
Node* copyRandomList(Node* head){
if (!head) return nullptr;
/* 将拷贝的节点接在原节点后面,再继续接下一个原节点 */
for (Node* cur = head; cur != nullptr; ){
Node* node = new Node(cur->val);
node->next = cur->next;
cur->next = node;
cur = node->next;
}
/* 确定每个新节点的random指向 */
for (Node* cur = head; cur != nullptr;) {
if (cur->random != NULL){
cur->next->random = cur->random->next;
}
else{
cur->next->random = NULL;
}
cur = cur->next->next;
}
/* 分离两个链表 */
Node dummy(-1);
Node* new_node = &dummy;
for (Node* cur = head; cur != nullptr; ){
new_node->next = cur->next;
if(cur->next != NULL){
cur->next = cur->next->next;
}
else{
cur->next = NULL;
}
new_node = new_node->next;
cur = cur->next;
}
return dummy.next;
}
};
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
for (RandomListNode* cur = head; cur != nullptr; ) {
RandomListNode* node = new RandomListNode(cur->label);
node->next = cur->next;
cur->next = node;
cur = node->next;
}
for (RandomListNode* cur = head; cur != nullptr; ) {
if (cur->random != NULL)
cur->next->random = cur->random->next;
cur = cur->next->next;
}
RandomListNode dummy(-1);
for (RandomListNode* cur = head, *new_cur = &dummy; cur != nullptr; ) {
new_cur->next = cur->next;
new_cur = new_cur->next;
cur->next = cur->next->next;
cur = cur->next;
}
return dummy.next;
}
};