方法一:利用map,空间复杂度O(N)
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head==NULL)
return NULL;
//先进行浅拷贝
//先设置一个哨兵节点,方便直接从头拷贝
RandomListNode *header=new RandomListNode(-1);
RandomListNode *p=header;
RandomListNode *q=head;
map<RandomListNode*,RandomListNode*> m;
while(q){//拷贝next指针
RandomListNode *tmp=new RandomListNode(q->label);
p->next=tmp;
m[q]=tmp;
p=p->next;
q=q->next;
}
//拷贝random指针
p=header->next;
q=head;
while(q){
p->random=m[q->random];
q=q->next;
p=p->next;
}
return header->next;
}
};
方法二:将每个节点都复制一遍,然后拷贝随机指针:副本节点的随机指针是原节点的随机指针的下一个节点;
空间复杂度为O(1)
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(head==NULL)
return NULL;
//先复制每一个节点,如原来是1->2->3->4,复制后变为1->1'->2->2'->3->3'->4->4'
RandomListNode *p=head;
while(p){
RandomListNode *tmp=new RandomListNode(p->label);
tmp->next=p->next;
p->next=tmp;
p=p->next->next;//走两步,跨过新加入的节点
}
//复制Random指针
p=head;
RandomListNode *q=head->next;
while(p){
if(p->random)
q->random=p->random->next;
p=p->next->next;//注意,此处要走两步
if(q->next)
q=q->next->next;//注意,此处要走两步
}
//分离两个链表:即分为1->2->3->4和1'->2'->3'->4'
p=head;
q=head->next;
RandomListNode *newHead=q;
RandomListNode *tmp1=NULL;
RandomListNode *tmp2=NULL;
while(p){
tmp1=p->next->next;
if(q->next==NULL)
break;//1->1'的情况在此退出(链表遍历到最后两个节点时也从此处退出)
tmp2=q->next->next;//此处:链表至少有4个节点1->1'->2->2'
p->next=tmp1;
q->next=tmp2;
p=p->next;
q=q->next;
tmp1=tmp1->next->next;//链表至少有4个节点1->1'->2->2',所以可以保证tmp1往后移动一次
if(tmp2->next)
tmp2=tmp2->next->next;
else
tmp2=NULL;//即tmp2已经是链表最后一个节点,此时会在下次一进入while时,从break处退出(q->next==NULL)
}
p->next=NULL;
return newHead;
}
};