文章目录
- 随机链表的复制
随机链表的复制
链接:随机链表的复制
这个题简单而言就是它给一个链表,每个结点包含两个指针,分别指向下一个和一个随机的结点(也有可能指向空),你要做的就是复制这个链表,使你创建的链表的结点也分别指向你创建的链表的结点的下一个值和对应的那个随机值。
这道题的难点是原链表中那个随机指针的指向在新链表中并不能用,你得找到新链表中对应的那个位置才可以,当然我们可以暴力求解,就是先复制链表的data和next值,先不管random,创建好了之后就去找原链表中每个结点的random值是NULL还是第几个结点的指针,两个指针指向两个链表中的对应相同的位置去找。
struct Node* copyRandomList(struct Node* head) {
struct Node*cur=head;
struct Node*newhead=NULL,*tail=NULL;
//下边是去创建新链表
while(cur!=NULL){
struct Node*tmp=(struct Node*)malloc(sizeof(struct Node));
tmp->val=cur->val;
tmp->next=NULL;
tmp->random=NULL;
if(newhead==NULL){
newhead=tail=tmp;
}
else{
tail->next=tmp;
tail=tail->next;
}
cur=cur->next;
}
//下边管random
cur=head;
struct Node*copycur=newhead;
while(cur!=NULL){
struct Node*tmp1=head;
struct Node*tmp2=newhead;
while(cur->random!=tmp1){//去找对应的位置,如果为空就是最后一个位置,也能找到
tmp1=tmp1->next;
tmp2=tmp2->next;
}
copycur->random=tmp2;
cur=cur->next;
copycur=copycur->next;
}
return newhead;
}
上面是暴力求解的过程,时间复杂度都已经O(N^2),那么如何简化一下算法呢?我们的问题是找不到random的值,那我们就想法让它有迹可循,方法是:我们把复制的结点创建到原链表的每个对应的结点的后面,那就不管next,先管random,random的值就是原结点的random的值的下一个,之后再把新结点摘下来,组成一个新的链表,恢复原链表,可能这么说有点抽象,我们画图来看一下
struct Node* copyRandomList(struct Node* head) {
//先在每个结点后面添加一个相同的结点
struct Node* cur=head;
while(cur){
struct Node*newnode=(struct Node*)malloc(sizeof(struct Node));
newnode->val=cur->val;
struct Node*next=cur->next;
cur->next=newnode;
newnode->next=next;
cur=next;
}
//处理拷贝结点的random
cur=head;
while(cur){
if(cur->random==NULL){
cur->next->random=NULL;
}
else{
cur->next->random=cur->random->next;
}
cur=cur->next->next;
}
//把拷贝的结点摘下来并且恢复原链表
cur=head;
struct Node*newhead=NULL,*tail=NULL;
while(cur){
struct Node*copy=cur->next;
struct Node*next=copy->next;
if(newhead==NULL){
newhead=tail=copy;
}
else{
tail->next=copy;
tail=tail->next;
tail->next=NULL;
}
cur->next=next;
cur=next;
}
return newhead;
}