此题要求深拷贝链表,该链表中每个结点额外增加了一个random指针,该random指针或为NULL或指向任意一个结点。
深拷贝&浅拷贝
优快云中较为通俗易懂的比喻:
老师给你们留了作业,你们班只有小明一个人做了,其他人都需要copy他的作业,如果你们都是通过浅拷贝来完成作业,那么就相当与“在你需要的时候,小明会把作业借给你”。
例如:老师要检查小红的作业,小红就去把小明的作业带给老师看,轮到小虎时,小虎就再向小明借。但如果说”把你们的作业全部交上来“,那么你们就完蛋了。
深拷贝就是每个人都实实在在的抄了一份作业,即使老师最后要求大家一起交上去也没有问题。
如果要对一个链表进行深拷贝,则需要创建这个链表中的所有表结点对象,再将这些对象按照原来的关系链接起来,这时存在两条链表,内存中增加了一倍的存储(增加了n个对象引用,以及为这些对象分配的n个空间)。
若为浅拷贝,只是拷贝了一个链表对象引用,并为这个引用分配了相应的空间,内存中仅仅是多了一个对象的引用(4个字节,栈区分配)以及一个对象(堆区分配)。
此题的难点在于节点中的random指针,因为深拷贝是重新开辟的空间,所以,random指针的赋值是一个较大的问题。
下面链接是youku上讲解深拷贝链表的视频,很不错。
http://v.youku.com/v_show/id_XNjU1NzI0NDAw.html
具体思路:
1,在原链表中每个结点的后面copy一个新结点,random先不做处理
2,根据原理可知新建结点的random指针与原结点random指针的关系 ,即:new->random = old->random->next
3,依次拆分链表得到原链表和深拷贝后得到的新链表
如图(图片来自http://www.cnblogs.com/TenosDoIt/p/3387000.html)
代码如下:
class Solution
{
public:
RandomListNode *copyRandomList(RandomListNode *head)
{
RandomListNode *p, *temp, *copyHead;
p = head;
if(head == NULL)
return head;
//遍历第一遍copy结点
while(p!=NULL)
{
temp = new RandomListNode(p->label);
temp->next = p->next;
p->next = temp;
p = p->next->next;
}
//遍历第二遍为random赋值
p = head;
while(p!=NULL)
{
RandomListNode *q = p->next;
if(p->random == NULL)
q->random = NULL;
else
q->random = p->random->next;
p = p->next->next;
}
//遍历第三遍拆分链表
p = head;
copyHead = new RandomListNode(0);
temp = copyHead;
while(p!=NULL)
{
temp->next = p->next;
temp = temp->next;
p->next = p->next->next;
p = p->next;
}
return copyHead->next;
}
};