链表OJ题目详解(11)---复制带随机指针的链表

题目描述

题目分析:

 这道题乍一看很复杂,其实不是很难,意思就是让你原封不动地复制一个链表,不过这个链表特殊一点,不仅每个节点有指向下一个节点的指针,还有一个指向了该链表中某个随机节点的指针

解题思路

①拷贝节点插入到新节点的后面

②控制拷贝节点的random

③拷贝节点接下来尾插组成拷贝链表,并且恢复原链表

①拷贝节点插入到新节点的后面

 

 之前单链表那篇博客就已经详细讲解了增删查改相关问题,这里就不赘述了~

②控制拷贝节点的random

这一步要做的事情就是把复制节点的random指向它该指的位置(和对应的原链表的节点一致)

分析一下前两个拷贝节点的ramdom情况~

7这个拷贝节点的ramdom

 由于原链表7这个节点的random是指向空的,因此拷贝节点的random也指向空即可

13这个拷贝节点的ramdom

 由于原链表13这个节点的ramdom是指向7这个节点,因此13这个拷贝节点的ramdom也应该指向拷贝节点7,那怎么找自己的拷贝节点7呢?别忘了,在第一步中,我们已经将每个拷贝节点插入到了原链表节点的后面,假设指向当前节点的指针是cur,因此只需要 copy->random = cur->random->next(核心代码)  这句代码就可以实现,再让cur = copy->next就可以往后遍历了~

 ③拷贝节点解下来尾插组成拷贝链表,并且恢复原链表

 

 解下来第1个拷贝节点,恢复第1个和第2个节点之间的链接

 

 解下来第2个拷贝节点,尾插到第1个节点后面,恢复第2个和第3个节点之间的链接

 

 后面的过程依次类推~~

完整代码

struct Node* copyRandomList(struct Node* head) {
    struct Node* cur = head;
    //1.拷贝节点插到原节点后面
    while(cur)
    {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;

        struct Node* next = cur->next;
        cur->next = copy;
        copy->next = next;

        cur = next;
    }

    //2.控制拷贝节点的random
    cur = head;
    while(cur)
    {
        struct Node* copy = cur->next;
        if(cur->random == NULL)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }
        cur = copy->next;
    }
    
    //3.拷贝节点解下来尾插组成拷贝链表,并且恢复原链表
    struct Node* copyHead = NULL, *copyTail = NULL;
    cur = head;
    while(cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;
        if(copyTail == NULL)
        {
            copyTail = copyHead = copy;
        }
        else
        {
            copyTail->next = copy;
            copyTail = copyTail->next;
        }
       cur->next= next;
       cur = next;
    }
    return copyHead;
}

 本篇博客就分享到这啦,欢迎大家交流指正~

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值