给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深度拷贝。
题目的意思:
题目的意思指的是拷贝后的新链表上每一个结点的随机指针也应该指向和原链表位置对应的结点
也就是说,我们在拷贝链表的时候,新链表上的每一个结点的随机指着都应该指向新链表上位置和旧链表对应的结点
思路:
是无法通过一次性就建好链表的,比如说在建第一个结点的时候,第一个的结点的随机指针指向第4个结点,由于我们第4个结点还没创建,所以不可能一次性就把所有随机指针都初始化好
所以,深度拷贝链表,至少需要二次操作:
我们可以先建一次链表,不初始化随机指针,只初始化结点的值
然后再遍历一遍链表,把随机指针补充好
通过分析发现,如果通过从头到尾遍历去找要随机指针,效率肯定是非常慢的,比如说第一个结点的随机指针指向第99个结点,我们则需要从第一个结点不断next才可以找到第99个结点,所以这种从头到尾遍历找随机指针的方法非常慢,不可行
所以我们可以用一个Map,存原结点到新结点的一一对应关系,原链表第一个结点的映射就是新链表的第一个结点,原链表第二个结点的映射就是新链表的第二个结点,以此类推
那么我们在找随机指针的时候,就可以变快很多,比如说第一个结点的随机指针指向第99个结点,那么我们直接找原链表的第一个结点的随机指针,然后映射出对应的指针,就找到了
效率:98.22%
code:
/**
* 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) {}
* };
*/
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if (!head)
return NULL;
RandomListNode * ret = new RandomListNode(head -> label);
RandomListNode *cope_ret_head = ret, *temp_head = head;
map<RandomListNode*,RandomListNode*> m;
m[temp_head] = ret;
while (temp_head = temp_head -> next) {
RandomListNode * t = new RandomListNode(temp_head -> label);
ret -> next = t;
ret = ret -> next;
m[temp_head] = ret;
}
temp_head = head;
ret = cope_ret_head;
while (temp_head) {
ret -> random = m[temp_head -> random];
temp_head = temp_head -> next;
ret = ret -> next;
}
return cope_ret_head;
}
};