随机链表的复制

这篇具有很好参考价值的文章主要介绍了随机链表的复制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🍉前言

果然,力扣的简单题不一定简单,但是中等和较难的题一定很麻烦。
这道题相当综合,对于思路二,如果看完思路后能写出代码,那说明你链表掌握得相当熟练了。

🍉题目

题目链接
随机链表的复制,初阶数据结构,链表,数据结构,c语言,开发语言,算法
随机链表的复制,初阶数据结构,链表,数据结构,c语言,开发语言,算法

🍉分析

题干很长,不过总结下来就很简单的几句话:有一链表,它每个节点除了有next,还有个random指针,random指向哪里?不知道,可能是其他节点,也可能指向NULL。然后现在要你对这样一个链表进行拷贝,得到一个新链表,新链表中每个节点random的指向和原链表一模一样。

🍉思路一:暴力解法

先复制原链表,但不复制random指针,得到一个新链表。接下来要复制 random 指针,那我们得知道它指向原链表的第几个节点,假设现在要得到第一个节点 node1 的random指向哪,那就遍历链表,直到某个节点的地址和 node1->random 一样,此时该节点就是 node1 的 random,然后要记录这个节点的位置(即第几个节点),比如 node1 指向第三个节点,那你新链表第一个节点也要指向第三个节点。(这里注意不是指向原链表的第三个节点!);如果没有找到,那就说明node1->random = NULL。
既然现在已经知道第一个节点的 random 指向第三个节点,那就遍历新链表,先遍历得到第一个节点(这里因为刚好是第一个节点,所以不用遍历,但如果不是第一个,那就要遍历了),再遍历一次找到第三个节点,然后就可以将它的地址赋给random了。
随机链表的复制,初阶数据结构,链表,数据结构,c语言,开发语言,算法

顺便来分析一下时间复杂度,最坏的情况是所有节点的 random 都指向最后一个节点,此时原链表中每个节点要找n次才能找到random指向的节点,有n个节点,所以就是n ^ 2;而新链表也是如此,所以时间复杂度就是O(N^2)。

这个解法比较复杂,代码的话你自行尝试咯。


🍉思路二:很绝的办法

之前的难点来源于原链表和新链表之间没有建立起联系。那么我们现在不妨这样:拷贝节点放在原链表对应的节点的后面,比如拷贝的第一个节点就插在原链表第一和第二个节点之间。最终效果如下图(黄色的表示新链表插进来的节点)
随机链表的复制,初阶数据结构,链表,数据结构,c语言,开发语言,算法

那么这样做有啥好处呢?假设原链表第一个节点的random指向第三个节点,那么新链表第一个节点的random 不就是第三个节点的下一个节点了吗?
说白了就是把“变”的化为“不变”,原先一个节点的random不是随便指吗?这就是“变”;而我现在可以用这种固定的方式去得到新链表所有节点random指针的指向,这是“不变”。

这种解法虽然很巧妙,但是写起来也是很麻烦的,不过嘛,相较于思路一,思路二的时间复杂度是O(N),这就是一个大提升。

第一步,先创建新链表的节点,然后插入,这个操作类似指定位置之后插入。

	typedef struct Node Node;
	Node* cur = head;
    //插入新链表的节点
    while(cur) {
        Node* next = cur->next;  //放循环里面其实是为了防止next为空
        Node* copy = (Node*)malloc(sizeof(Node));    //copy:待插入的新节点
        copy->val = cur->val;
        copy->next = next;
        cur->next = copy;
        cur = next;
    }

第二步,设置插入节点的random指针,(记得先将 cur 置为head)

	cur = head;
    while(cur) {
        Node* copy = cur->next;
        if(cur->random == NULL) {
            copy->random = NULL;
        } else {
            copy->random = cur->random->next;    //这一步最关键!
        }
        cur = copy->next;
    }

第三步,把新节点取出来,连起来就是拷贝后的链表了,记得把原链表拼接回去

	cur = head;
    Node* newhead = NULL,*newtail = NULL;     //创建新链表,然后刚才的新节点进行尾插
    while(cur) {
        Node* copy = cur->next;
        if(newhead == NULL) {
            newhead = newtail = copy;
        } else {
            newtail->next = copy;
            newtail = newtail->next;
        }
        cur = copy->next;
    }
    return newhead;

整个函数的代码:文章来源地址https://www.toymoban.com/news/detail-758011.html

typedef struct Node Node;
struct Node* copyRandomList(struct Node* head) {
	Node* cur = head;
    //插入新链表的节点
    while(cur) {
        Node* next = cur->next;  //放循环里面其实是为了防止next为空
        Node* copy = (Node*)malloc(sizeof(Node));
        copy->val = cur->val;
        copy->next = next;
        cur->next = copy;
        cur = next;
    }
    //设置新节点的random指针
    //先重置cur、copy
    cur = head;  
    while(cur) {
        Node* copy = cur->next;
        if(cur->random == NULL) {
            copy->random = NULL;
        } else {
            copy->random = cur->random->next;
        }
        cur = copy->next;
    }
    //把新节点的random处理好之后,接下来要把这些新节点与原先节点分离,恢复原链表
    cur = head;
    Node* newhead = NULL,*newtail = NULL;
    while(cur) {
        Node* copy = cur->next;
        if(newhead == NULL) {
            newhead = newtail = copy;
        } else {
            newtail->next = copy;
            newtail = newtail->next;
        }
        cur = copy->next;
    }
    return newhead;
}

到了这里,关于随机链表的复制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】LeetCode升级版的环形链表,复制带随机指针的链表

              1、题目说明           2、题目解析           1、题目说明           2、题目解析      1、题目说明 题目链接: 升级版的环形链表  给定一个链表的头节点 head ,返回链表开始入环的第一个节点。  如果链表无环,则返回NULL。 如果链表中有某个节点,可以通

    2024年01月16日
    浏览(42)
  • 随机链表的复制

    果然,力扣的简单题不一定简单,但是中等和较难的题一定很麻烦。 这道题相当综合,对于思路二,如果看完思路后能写出代码,那说明你链表掌握得相当熟练了。 题目链接 题干很长,不过总结下来就很简单的几句话:有一链表,它每个节点除了有next,还有个 random指针 ,

    2024年02月04日
    浏览(21)
  • <数据结构> 链表 - 链表的概念及结构

    概念: 链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的 逻辑顺序 是通过链表中的 指针链接 次序实现的 1、链表由一系列结点(链表中每一个元素称为结点)组成。 2、结点可以在运行时动态(malloc)生成。 3、每个结点包括两个部分:一个是存储数据元素的

    2023年04月09日
    浏览(32)
  • 初阶数据结构:链表

    经过学习与练习,已经掌握了顺序表的相关知识并且能够自我实现。在这一过程中,通过对其结构的实现,发现顺序表的尾部插入删除数据效率很高,可是,在 头部与随机插入的场景下效率低下 而且 存在扩容消耗 等一些问题。而有这样一种数据结构可以很好的解决顺序表存

    2024年01月20日
    浏览(31)
  • 【数据结构】反转链表、链表的中间节点、链表的回文结构(单链表OJ题)

    正如标题所说,本文会图文详细解析三道单链表OJ题,分别为:  反转链表 (简单)  链表的中间节点 (简单)  链表的回文结构 (较难) 把他们放在一起讲的原因是:  反转链表 和  链表的中间节点 是  链表的回文结构 的基础 为什么这样说?请往下看: 目录 1. 反转链

    2024年02月13日
    浏览(39)
  • 【数据结构】链表的回文结构

    单链表的操作算法是笔试面试中较为常见的题目。 本文将着重介绍平时面试中常见的关于链表的应用题目,马上要进行秋招了。希望对你们有帮助 _ 😀 对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。 给定一个链表的头指针

    2024年02月12日
    浏览(41)
  • 初阶数据结构(三)链表

    💓博主csdn个人主页:小小unicorn💓 ⏩专栏分类:c++ 🚚代码仓库:小小unicorn的学习足迹🚚 🌹🌹🌹关注我带你学习编程知识 前面我们讲的线性表的 顺序存储结构 。它是有缺点的,最大的缺点就是插入和删除时需要移动大量元素,这显然就需要 耗费时间 ,那能不能想办法

    2024年02月09日
    浏览(41)
  • 初阶数据结构之单链表的实现(四)

    链表的概念 :链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。 所谓的逻辑结构其实就是能让我们自己能够更好的理解这个东西是什么?那么我们就用画图来理解理解吧!!在单链表中,存放着两个量,一个

    2024年02月06日
    浏览(25)
  • 【数据结构初阶】链表OJ

    OJ 方案一: 题目解析: 方案二: 题目解析:把原链表遍历一遍,插入新链表 OJ 题目解析: OJ 题目解析: OJ 题目解析: OJ 题目解析: OJ 题目解析: OJ 题目解析: OJ 题目解析: 定义快慢指针,使快指针先走与慢指针同步。然后同时走看是否相交 OJ 题目解析: OJ 题目解析:

    2024年02月05日
    浏览(37)
  • 【LeetCode刷题日志】138.随机链表的复制

    🎈个人主页:库库的里昂  🎐C/C++领域新星创作者  🎉欢迎 👍点赞✍评论⭐收藏 ✨收录专栏:LeetCode 刷题日志 🤝希望作者的文章能对你有所帮助,有不足的地方请在评论区留言指正,大家一起学习交流!🤗 目录 1.题目描述 2.解题思路+代码实现 方法:迭代 + 节点拆分 思

    2024年02月04日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包