题目:
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深拷贝。
示例:
输入:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}
解释:
节点 1 的值是 1,它的下一个指针和随机指针都指向节点 2 。
节点 2 的值是 2,它的下一个指针指向 null,随机指针指向它自己。
提示:
你必须返回给定头的拷贝作为对克隆列表的引用。
分析:
分三步走:(1)拷贝原链表节点(2)置每个节点的random指针(注意不空和空的时候都要进行置)(3)拆分原链表
//RandomListNode* Clone(RandomListNode* pHead)
Node* copyRandomList(Node* head)
{
if(head==nullptr)
return nullptr;
//第一步:复制链表结点
Node* oldnode=head;
while(oldnode)
{
Node* newnode = new Node(oldnode->val);
//用老节点的值申请一个新节点
newnode->next=oldnode->next;
//将新节点的next链上老节点的next
oldnode->next=newnode;
//将新节点插在老节点后面
if(oldnode->next)
oldnode=oldnode->next->next;
//由于已经插入了新节点,因此遍历下一个老节点得走2个next
}
//第二步:置信结点的random指针klll'``
oldnode=head;
//oldnode指向链表的开始
while(oldnode)
{
Node* newnode=oldnode->next;
//由于上面的复制,新节点紧跟在与其对应的老节点后面
if(oldnode->random!=nullptr)
{
//oldnode->random是老节点的random域,再指向next就是该老节点对应的新节点应该指向的对应的random域
newnode->random=oldnode->random->next;
}
else//当老节点的random指针域为空时,也要将新节点的random指针域置空
{
newnode->random=nullptr;
}
oldnode=oldnode->next->next;
//只走老节点(为其对应的新节点链上对应的randoum域)
}
//拆分新/老链表
oldnode=head;
//让oldnode指向链表开始
Node* newHead=oldnode->next;
//新链表的头是老链表头的下一个(之前复制了的)
while(oldnode)
{
Node* newnode=oldnode->next;
//保证newnode一直紧跟咋oldnode后面(老、新节点相对位置)
if(newnode != nullptr)
oldnode->next=newnode->next;//恢复老节点的next指向
if(oldnode->next!=nullptr)
{
newnode->next=oldnode->next->next;
//恢复新节点的next指向
}
oldnode=oldnode->next;//由于oldnode的next域上面已经恢复了,因此下一个老节点就是oldnode->next
}
return newHead;
}
/*Node* copyRandomList(Node* head)
{
if(head==nullptr)
return nullptr;
//复制
Node* old=head;
while(old)
{
Node* newnode=new Node(old->val);//利用旧节点创建新节点
newnode->next=old->next;
old->next=newnode;
old=old->next->next;//插入一个新的,但是每次都只走旧节点
}
//置randow指针
old=head;
while(old)
{
Node* newnode=old->next;//新节点
if(old->random)
{
newnode->random=old->random->next;
}
else
{
newnode->random=nullptr;
}
old=old->next->next;//只走旧节点
}
//拆分
old=head;//旧头
Node* newHead=old->next;//新头
while(old)
{
Node* newnode=old->next;//一直在old后面,即被复制的节点
//old=next->next;//回复旧节点指向
old->next=newnode->next;
if(old->next)
newnode->next=old->next->next;//回复老的节点指向
old=old->next;//由于上一个新老节点均恢复指向,因此只需原来的而节点移动
}
return newHead;
}*/