给出一个链表,每个节点包含一个额外增加的随机指针可以指向链表中的任何节点或空的节点。
返回一个深拷贝的链表。
/**
* Definition for singly-linked list with a random pointer.
* struct RandomListNode {
* int label;
* RandomListNode *next, *random;
* RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
* };
*/
class Solution {
public:
/**
* @param head: The head of linked list with a random pointer.
* @return: A new head of a deep copy of the list.
*/
RandomListNode *copyRandomList(RandomListNode *head) {
if(head == NULL)
return NULL;
RandomListNode* pCloneHead = new RandomListNode(head->label);
pCloneHead->next = head->next;
pCloneHead->random = head->random;
pCloneHead->next = copyRandomList(head->next);
return pCloneHead;
}
};
1.首先从左到右遍历链表,对每个节点都复制生成相应的副本节点,然后把副本节点放在当前节点和下一个要遍历节点的中间。
2.再从左到右遍历链表,在遍历时设置每一个副本节点的random指针。
3.此时所有的节点与副本节点串在一起,将其分离即可。
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if (head==NULL) return NULL;
nodeClone(head);
connectRandom(head);
return reconnect(head);
}
//[1]复制结点,插入到原结点后方
void nodeClone(RandomListNode *head)
{
RandomListNode *pNode = head;
while (pNode != NULL)
{
RandomListNode *pClone = new RandomListNode(pNode->label);
pClone->next = pNode->next;
pNode->next = pClone;
pNode = pClone->next;
}
}
//[2]还原新结点的random指针
void connectRandom(RandomListNode *head)
{
RandomListNode *pNode = head;
while (pNode != NULL)
{
RandomListNode *pClone = pNode->next;
if (pNode->random)
{
pClone->random = pNode->random->next;
}
pNode = pClone->next;
}
}
//[3]拆分
RandomListNode *reconnect(RandomListNode *head)
{
RandomListNode *p = head;
RandomListNode *result = p->next;
RandomListNode *pp = result;
while(p){
if(p->next->next){
p->next = p->next->next;
pp->next = pp->next->next;
}else{
p->next = NULL;
pp->next = NULL;
}
p = p->next;
pp = pp->next;
}
return result;
}
};