力扣138.复制带随机指针的链表

138. 复制带随机指针的链表 - 力扣(LeetCode)

        题目要求是把它给你的长度为N的链表复制一份返回,但是由于它有个random指向随机的的节点,如果创建新链表,每次遍历一下这个链表去复制到新链表的话时间复杂度很大,一但链表过长就不知道执行到猴年马月了,所以可以在原链表上用3个循环完成目的。

        第一步,复制节点和节点中的值。我们可以把复制的节点(copy)链接在被复制节点(cur)的后面,然后把copy->next链接到cur下一个节点(next),再把cur指向next,当cur为NULL时,完成第一个循环 。至于为什么不链接到cur的前面,下一步循环会提到。

如图所示

        第二步,复制 随机指针random。将cur置为头节点,copy指向复制节点,即cur->next,将copy的random指针指向cur->random,由于复制节点copy->random指向的也是复制的节点,那么每个复制节点都在原节点random的后面(->next),可以赋值。这里要考虑两种情况:

第一种情况cur->random可能为NULL,则copy->random=NULL

第二中情况cur->random不为NULL,则copy->random=cur->random->next

 所以要在循环中加一个if语句来判段原节点的random是否为NULL。复制下一个节点的random时cur直接指向copy->next即可,cur为NULL时结束循环。

        在这个循环中就可以发现,如果复制的节点原节点的前面,那么当你找到原节点时,random要链接到原节点的复制节点,是往前找了,单链表无法回头找节点,所以不能把复制的节点放在前面。

第三步,分裂,把复制的节点依次链接到新链头组成要返回的新的链表,即是尾插,再还原原链表。这时候就要创建一个新的头指针(copyHead)和尾指针(copyTail)来尾插链表,再返回copyHead即可。

 完成循环后得到如图,循环结束的条件依旧是cur为NULL

实现代码如下

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {
	struct Node* cur=head;
    while(cur)
    {
        struct Node* next=cur->next;
        struct Node* copy=(struct Node*)malloc(sizeof(struct Node));//开辟新空间
        copy->val=cur->val;//复制链表中的值
        //链接
        cur->next=copy;
        copy->next=next;
        cur=next;    //当next(cur->next)=NULL时结束循环
    }
    cur=head;//回到头结点
    while(cur)
    {   
        struct Node* copy=cur->next;
       
        if(cur->random==NULL)    //判断cur的random是否指向NULL
        {
            copy->random=NULL;
        }
        else
        {
            copy->random=cur->random->next;//如果random指向的不为NULL 则把结点的复制结点给它
        }
        cur=copy->next;    //后移,copy的下一个节点是原节点
    }
    cur=head;    //再回到头节点
    struct Node* copyHead=NULL,*copyTail=NULL; //新链表的头指针和尾指针,用来完成尾插
    while(cur)
    {
        struct Node* copy=cur->next;
        struct Node* next=copy->next;
        cur->next=next;

        if(copyTail==NULL)    
        {
            copyHead=copyTail=copy;//初始化复制的链表
        }
        else    //尾插
        {
            copyTail->next=copy;    
            copyTail=copyTail->next;    
        }
        
        cur=next;
    }
    return copyHead;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值