leetcode Copy List with Random Pointer

本文介绍一种特殊链表的深拷贝方法,该链表的节点包含一个额外的随机指针。文章详细解释了深拷贝与浅拷贝的区别,并提供了一个三步走的具体实现方案:首先复制节点并插入原节点之后,接着设置新节点的随机指针,最后拆分链表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



此题要求深拷贝链表,该链表中每个结点额外增加了一个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;	
	}


};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值