A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
链表数据结构如下所示:
/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/
要拷贝一个链表,这个链表跟平时见到的链表不太一样,就是每个节点还有一个成员random,可能是NULL,也可能指向链表中的任何一个节点。
那应该怎么拷贝呢?就是根据原链表的节点构造新链表的节点,但是新链表节点的random值要指向的是新链表中与原链表节点对应的节点。
第一种方案是可以先一个一个节点拷贝,不管random成员。构造完毕后,要改变新链表节点们的random值啦。从头开始扫描原链表,确定每个节点random的值,如果不是NULL,说明要对新链表节点的random赋值,那该如何赋值呢?肯定不是直接赋值为原链表的random值啦,要赋值为与原链表random指向的节点对应的新节点啦。那怎么知道原链表的节点对应的新节点呢,只要在拷贝原链表的每个节点过程中存储对应的新节点就行,STL的map容器这么好用就用它啦。
第二种方案是要拷贝原链表的每个节点时,搜索对应的新节点是否已经构造过,如果构造了就不用再new啦,如果没有构造,那么需要构造出新节点,然后要存储原节点与新节点的对应关系。如果原节点的random指针不为NULL,那么我们再检查random指向的节点对应的新节点是否已经被构造,如果已经构造过了,那么赋值为那个构造的节点就行啦,如果没有被构造,那么就构造新节点,再把映射关系存储下来。
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
RandomListNode *new_head, *p, *curr, *next;
map<RandomListNode*, RandomListNode*> mm;
new_head = NULL;
p = head;
while (p != NULL) {
next = new RandomListNode(p->label);
if (new_head == NULL) {
new_head = next;
} else {
curr->next = next;
}
mm.insert(make_pair(p, next)); // original list node 'p' map to new list node 'next'
curr = next;
p = p->next;
}
p = head;
curr = new_head;
/* after map the node pointers of original list into new pointers of new list,
we assign random pointers of new list nodes */
while (p != NULL) {
if (mm.find(p->random) != mm.end())
curr->random = mm[p->random];
p = p->next;
curr = curr->next;
}
return new_head;
}
};
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
RandomListNode *new_head, *p, *curr, *next, *random;
map<RandomListNode*, RandomListNode*> mm;
new_head = NULL;
p = head;
while (p != NULL) {
// copy node
if (mm.find(p) == mm.end()) {
next = new RandomListNode(p->label);
mm[p] = next; // store
} else {
next = mm[p]; // get
}
if (new_head == NULL) {
new_head = next;
} else {
curr->next = next;
}
// copy random
if (p->random != NULL) {
if (mm.find(p->random) == mm.end()) {
random = new RandomListNode(p->random->label);
mm[p->random] = random; // store
} else {
random = mm[p->random]; // get
}
next->random = random;
}
curr = next;
p = p->next;
}
return new_head;
}
};