给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深度拷贝。
第一个想法是利用哈希表,在C++11中的unordered_map(比map快不少)。对原链表每个节点,依次标号1、2、3。。。,生成从节点到编号的映射。对复制的现节点,也依次标号,生成从编号到节点的映射。然后根据映射关系补充随机指针。
RandomListNode *copyRandomList(RandomListNode *head)
{
unordered_map<RandomListNode*, int> map1;//从原链表到编号
unordered_map<int, RandomListNode*> map2;//从编号到现链表
RandomListNode* dummy = new RandomListNode(INT_MAX);
RandomListNode* p = dummy;
RandomListNode* ptr = head;
int cnt = 1;
while(head)
{
p->next = new RandomListNode(head->label);
map1.insert(make_pair(head, cnt));
map2.insert(make_pair(cnt, p->next));
p = p->next;
head = head->next;
cnt++;
}
while(ptr)//开始复制
{
int curIndex = map1[ptr];
int targetIndex = map1[ptr->random];
RandomListNode* curNode = map2[curIndex];
RandomListNode* targetNode = map2[targetIndex];
curNode->random = targetNode;
ptr = ptr->next;
}
return dummy->next;
}
但是这样的解法只能领先于56%的选手。后来发现只需要建立一个哈希表即可,保存从新节点和旧节点的映射。但这样空间复杂度为O(n),不够好。
剑指offer上提出了这样的做法:1、先在原链表的每个节点后面复制一个节点,然后添加随机指针(此时添加很容易),最后再将偶数节点串成链表。