题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
思路:
(1)在原来的链表每个节点后面添加一个节点,该节点下面连接着原来节点的下一个节点,并且该节点的值与前面连着的这个节点值相同,比如A->B->C,变成A->A’->B->B’->C->C’。A,A’; B,B’; C,C’ 的value分别相同
(2)新添加的节点的random分别指向对应的原节点random的下一个节点,什么意思呢,比如说:A->random=C,那么现在A’->random=C’,至此就完成了原来链表的复制,接下来是输出复制出来的链表
(3)将已经做好链表拆分,拆为A->B->C,A’->B’->C’。怎么拆呢,就是将每个节点的next指向其相隔的另一个节点,要注意的是,在断开相邻的两个节点的连接的时候,要先把后一个节点的位置先复制出来,要不待会儿前一个节点指向另外的节点了,后一个节点的位置就丢了。什么意思呢,比如说要断开A->A’的连接,让A->B,那么就要先把A’的指针先存起来(放到一个临时指针里),然后再让A->next指向B,然后再回过头来对A’进行操作,让它重新连接到B’。
具体实现结合下面代码来看:
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
//要有这个判断,没有会报错哦
if(pHead==NULL) return NULL;
//在每个节点之后插入复制点的节点
//这个是链表插入节点的操作,很简单
RandomListNode* headnode=pHead;
while(headnode)
{
RandomListNode* node=new RandomListNode(headnode->label);
node->next=headnode->next;
headnode->next=node;
headnode=node->next;
}
//将random指向的节点复制到新加入的节点上
headnode=pHead;
while(headnode)
{
if(headnode->random)
{
//headnode->random连接的是原来节点的random指针对应的节点,再指向next就指向了random后面新添加的节点
//比如A->random=C,A->random->next=C',这样A'->random就等于C'了
headnode->next->random=headnode->random->next;
}
//下面这句代码要写在if外面,因为headnode->random很可能指向的是NULL,如果指向了NULL,那么就要继续遍历接下来的节点。
headnode=headnode->next->next;
}
//将现在的链表每隔相连
//这个链表拆除的步骤可以结合我上面将的第三步来看,说一句,这里的clonenode用来保存复制的链表的头结点指针
RandomListNode* clonenode=pHead->next;
headnode=pHead;
while(headnode->next)
{
RandomListNode* tmp=headnode->next;
headnode->next=tmp->next;
headnode=tmp;
}
return clonenode;
}
};