LeetCode138——随机链表的复制(题解记录)

题目描述:

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

示例:

在这里插入图片描述

题目理解:

题目描述中的拷贝链表结点,提到了深拷贝,有深拷贝,那么就一定有浅拷贝,我们先来区分一下深拷贝和浅拷贝的区别。

  • 浅拷贝:
    浅拷贝只是复制指针的值,也就是只复制了对象的地址,而不会复制指针所指向的实际数据。这就导致原对象和拷贝对象会共享同一块内存空间,对其中一个对象的修改会影响到另一个对象。

  • 深拷贝:
    深拷贝不仅会复制指针的值,还会为拷贝对象分配新的内存空间,并将原对象的数据复制到新的内存空间中。这样,原对象和拷贝对象就拥有各自独立的内存空间,对其中一个对象的修改不会影响到另一个对象。

题目要求为深拷贝,那么在复制时就需要申请新的结点用来保存被复制结点的值。

题解:

题目示例中,每个结点由三个元素构成,分别为val,*next,*random。我们复制普通链表时,可以很容易的通过next指针找到后续结点,并进行复制,但此处random指针并不好处理。
所以我们采用一个巧妙的方法——申请节点后在被复制节点处进行后插。
在这里插入图片描述

在后插结束后,让pcur指针指向头结点,copy指针指第二个结点。
在这里插入图片描述
此时我们就会发现,利用这两个指针就可以更新新复制结点的random指针:
即:copy->random = pcur->random->next

在修改完所有复制节点random指针后,我们再将新复制结点从整个链表中抽离出来,就完成了原链表的深拷贝。

具体代码如下:

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

//1.创建新的结点,用于保存需要复制结点的val值,并将next和random指针置为空
Node* buynode(int x)
{
    Node* newnode = (Node*)malloc(sizeof(Node));
    newnode->val = x;
    newnode->next = newnode->random = NULL;
    return newnode;
}

//2.将新建立的结点插入在被复制的结点之后
void nodeinsert(Node* head)
{
    Node* pcur = head;
    while(pcur)
    {
        Node* pnext = pcur->next;
        Node* newnode = buynode(pcur->val);
        newnode->next = pcur->next;
        pcur->next = newnode;
        pcur = pnext;
    }
}

//3.修改已经创建好的结点的random指针,若pcur的random指针本身为空,则不需要更改
void setrandom(Node* head)
{
    Node* pcur = head;
    while(pcur)
    {
        Node* copy = pcur->next;
        if(pcur->random != NULL)
            copy->random = pcur->random->next;
        pcur = copy->next;
    }
}

struct Node* copyRandomList(struct Node* head) {
    //针对链表为空的情况特殊处理,若链表为空,直接返回空
    if(head == NULL)
        return NULL;
	//1.申请一个新的结点复制完成后插入在被复制的结点之后
    nodeinsert(head);
    //2.修改random指针的指向
    setrandom(head);
    //3.将复制的链表从原链表中抽离出来
    Node* pcur = head;
    Node*newhead,*ptail;
    newhead = ptail = pcur->next;
    while(ptail->next)
    {
        pcur = ptail->next;
        ptail->next = pcur->next;
        ptail = pcur->next;
    }
    //返回的newhead即为深拷贝链表
    return newhead;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值