复制带随机指针的链表【构造链表深拷贝】

简介: 复制带随机指针的链表【构造链表深拷贝】

复制带随机指针的链表



 先导知识点:单链表

复制带随机指针链表的要求

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

 要求:时间复杂度O(N),空间复杂度O(1)

 例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random--> y ,即每个节点的相对位置是一样的。

val 是一个整数

next 指向下一个节点

random 指向任意一个节点

 例如下面的链表,这个链表复制得到的链表除了每个节点的地址与此链表不同,其他部分必须与这个链表完全相同。

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]

输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

解题思路

 此题对时间复杂度和空间复杂度都有了限制,因此不能采用暴力求解的方式。

 难点:节点的 random 指针是指向随机的节点,不能使用传统思维模式,所以原始的拷贝链表的方法如果用在这里的话,可能无法处理后续问题。

 对于此题采用的方法如下:

  • 拷贝所有节点,放在对应原节点的后面。
  • 将每个 random 指向对应的位置。
  • 将复制的链表解下来,尾插到一起,并将原链表恢复。

 每个阶段使用完 cur 都要记得将 cur 置为 head 。

1、拷贝所有节点,并放在对应原节点的后面

每次开辟节点复制并直接尾插在原节点后面即可。

2.将每个 random 指向对应的位置。

  当将每个节点的复制节点尾插在原节点的后面之后,那么原节点的 random指向的位置的下一个节点,就是复制后节点的 random 指针要指向的位置

3.将复制的链表解下来,尾插到一起,并将原链表恢复

先将复制的链表解下来

 定义两个链表 copyhead copytail,copyhead 记录新链表的头节点,copytail 负责维护新节点尾插。用copytail 维护尾插的好处是不用每次循环找尾,只需要每次 copytail 后移即可。

然后再将原链表恢复,恢原链表只需要将链表的 next 指向下一个next就可以了。

源码

struct Node* copyRandomList(struct Node* head) {
    struct Node* cur = head;
    while (cur != NULL)
    {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        struct Node* next = cur->next; 
        copy->val = cur->val;
        cur->next = copy;
        copy->next = next;
        cur = next; 
    }
    cur = head;
    while (cur != NULL)
    {
        struct Node* copy = cur->next;
        if (cur->random == NULL)
            copy->random = NULL;
        else
        {
            copy->random = cur->random->next;
        }
        cur = copy->next;
    }
    cur = head;
    struct Node* copyhead = NULL, * copytail = NULL;
    while (cur != NULL)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;
        if (copytail == NULL)
        {
            copyhead = copytail = copy;
        }
        else
        {
            copytail->next = copy;
            copytail = copytail->next;
        }
        cur->next = next;
        cur = next;
    }
    return copyhead;
}

这段代码是力扣的核心代码模式,返回复制成功的链表头节点即可。

相关文章
|
4月前
链表指针的传参,传值和传地址
本文讨论了链表操作中指针传参的问题,特别是指针的传值与传地址的区别,并提供了修正代码,以确保链表插入操作能正确地修改指针指向的地址。
28 1
链表指针的传参,传值和传地址
|
9月前
|
存储 C语言
用指针处理链表
用指针处理链表
81 3
|
4月前
|
存储
一篇文章了解区分指针数组,数组指针,函数指针,链表。
一篇文章了解区分指针数组,数组指针,函数指针,链表。
33 0
|
4月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
56 0
|
7月前
【数据结构OJ题】复制带随机指针的链表
力扣题目——复制带随机指针的链表
66 1
【数据结构OJ题】复制带随机指针的链表
|
6月前
|
Python
【Leetcode刷题Python】138. 复制带随机指针的链表
LeetCode上题目“138. 复制带随机指针的链表”的Python解决方案,包括两种方法:一种是在每个节点后复制一个新节点然后再分离出来形成新链表;另一种是构建一个字典来跟踪原始节点与其副本之间的映射关系,从而处理新链表的构建。
33 1
|
6月前
|
存储 算法 数据处理
指针与链表
指针与链表
105 0
|
8月前
|
算法
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
|
9月前
|
存储 C语言
链表—初始化指针变和创建新的节点------区别应用分析
链表—初始化指针变和创建新的节点------区别应用分析
|
9月前
|
存储 缓存 搜索推荐
指针链表
指针链表
61 0

热门文章

最新文章