每日一题——复杂链表的复制

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

复杂链表的复制

题目链接

每日一题——复杂链表的复制,每日一题,# 链表相关,链表,数据结构,leetcode,c语言


思路

如果不考虑random指针的复制,仅仅复制单链表的结构还是简单的。只需要通过一个指针cur遍历原链表,再不断创建新节点尾插到newHead后即可。

但如果要考虑random指针的复制,那过程就复杂了。

有小伙伴会这样想:既然原链表和复制的链表的结构一致,那么对于原链表的任意一个节点,我们都可以先知道它们random指针的指向,这样就可以通过循环得到这是原链表的第几个节点,最后也就可以通过循环将复制链表的相同节点的random指针指向相同的位置了。但是对于每一个节点,每确定一个random指针时间复杂度就是O(N),一共N个节点时间复杂度就是O(N^2),显然效率不高。

接下来给大家讲解一个时间复杂度为O(N),空间复杂度为O(1)的方法:

  • 第一步:新建节点,复制链表的val值、next值

    这里我们不采用新建一个头newHead,然后将新建的节点尾插到newHead后的方法。

    这里我们利用交织链表的方法:cur遍历原链表,每遍历一个节点就将复制的节点插入到这个节点之后。形象一点来说就是,如果原链表为A->B->C->NULL,那么这一步过后,链表就变成了A->A'->B->B'->C->C'->NULL

struct Node* cur = head;

//先创建交织链表
while (cur)
{
    struct Node* temp = (struct Node*)malloc(sizeof(struct Node));

    temp->val = cur->val;
    temp->next = cur->next;
    cur->next = temp;

    cur = cur->next->next;
}
  • 第二步:完成random指针的复制

    实现了上面交织链表的操作,我们就可以直接得到复制链表的节点的random指着的指向了:

    即为其原节点 S 的随机指针指向的节点 T 的后继节点 T'。需要注意原节点的随机指针可能为空,我们需要特别判断这种情况。

    通过下图也可以理解对应的关系:

每日一题——复杂链表的复制,每日一题,# 链表相关,链表,数据结构,leetcode,c语言

//复制random指针
cur = head;

while (cur)
{
    struct Node* temp = cur->random;    //找到随机指针的指向

    if (temp == NULL)
        cur->next->random = NULL;
    else
        cur->next->random = temp->next;

    cur = cur->next->next;
}
  • 最后一步,将交织的链表拆成两串链表,返回复制链表的头

    虽然我们也可以不对原链表进行还原,但安全起见,最好不要改变原有的链表结构文章来源地址https://www.toymoban.com/news/detail-627939.html

struct Node* retHead = head->next;	//要返回的头节点
struct Node* cur1 = head;
struct Node* cur2 = retHead;

//取消交织,还原为两个链表
while (cur1 && cur2->next)
{
    cur1->next = cur1->next->next;
    cur2->next = cur2->next->next;

    cur1 = cur1->next;
    cur2 = cur2->next;
}

cur1->next = NULL;
cur2->next = NULL;

//最后返回复制链表
return retHead;

实现代码

struct Node* copyRandomList(struct Node* head) {
    if (head == NULL)
        return NULL;

	struct Node* cur = head;

    //先创建交织链表
    while (cur)
    {
        struct Node* temp = (struct Node*)malloc(sizeof(struct Node));

        temp->val = cur->val;
        temp->next = cur->next;
        cur->next = temp;

        cur = cur->next->next;
    }

    //复制随机指针
    cur = head;

    while (cur)
    {
        struct Node* temp = cur->random;    //找到随机指针的指向

        if (temp == NULL)
            cur->next->random = NULL;
        else
            cur->next->random = temp->next;

        cur = cur->next->next;
    }

    //取消交织
    struct Node* retHead = head->next;	//要返回的头节点
    struct Node* cur1 = head;
    struct Node* cur2 = retHead;

    //取消交织,还原为两个链表
    while (cur1 && cur2->next)
    {
        cur1->next = cur1->next->next;
        cur2->next = cur2->next->next;

        cur1 = cur1->next;
        cur2 = cur2->next;
    }

    cur1->next = NULL;
    cur2->next = NULL;

    //最后返回复制链表
    return retHead;
}

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

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

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

相关文章

  • (链表) 剑指 Offer 52. 两个链表的第一个公共节点 ——【Leetcode每日一题】

    难度:简单 输入两个链表,找出它们的第一个公共节点。 如下面的两个链表: 在节点 c1 开始相交。 示例 1: 输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3 输出:Reference of the node with value = 8 输入解释:相交节点的值为 8 (注意,如果两个列表相交则

    2024年02月15日
    浏览(53)
  • 力扣每日一道系列 --- LeetCode 138. 随机链表的复制

    📷 江池俊: 个人主页 🔥个人专栏: ✅数据结构探索 ✅LeetCode每日一道 🌅 有航道的人,再渺小也不会迷途。 LeetCode 138. 随机链表的复制 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的

    2024年02月04日
    浏览(47)
  • 算法每日一题: 删除排序列表中的重复元素2 | 循环 | 链表的删除 | 虚拟节点

    大家好,我是星恒 今天的题目是昨天题目的进化题,他对链表的删除加深了理解。最重要的是学会了对循环中的特殊部分的处理,还有设置虚拟节点的情况 好了,话不多说,我们直接开始 题目:leetcode 82 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点

    2024年01月16日
    浏览(39)
  • C语言每日一题:11.《数据结构》链表分割。

    题目链接: 1.构建两个新的带头链表,头节点不存储数据。 2.循环遍历原来的链表。 3.小于x的尾插到第一个链表。 4.大于等于x尾插到第二个链表。 5.进行链表合并,注意第二个链表的尾的下一个需要置空防止成环。 6.free两个头之前需要保存新的满足条件的单链表的头。 1.有

    2024年02月14日
    浏览(46)
  • C语言每日一题:13《数据结构》环形链表。

    题目链接: 使用快慢指针利用相对移动的思想: 1,令快指针(fast)速度为2. 2.慢指针(slow)速度为1. 3.以慢指针进入环中开始。 4。假设slow刚刚进入环中fast与它相距N。 如图所示: 1,令快指针(fast)速度为3.M 2.慢指针(slow)速度为1. 3.以慢指针进入环中开始。 4。假设slow刚

    2024年02月14日
    浏览(46)
  • 【数据结构与算法——TypeScript】算法的复杂度分析、 数组和链表的对比

    什么是算法复杂度(现实案例)? ❤️‍🔥 前面已经解释了什么是算法? 其实就是解决问题的一系列步骤操作、逻辑。 ✅ 对于同一个问题,我们往往有很多种解决思路和方法,也就是可以采用不同的算法。 举个例子(现实例子):在一个庞大的图书馆中,我们需要找一本书

    2024年02月14日
    浏览(53)
  • 随机链表的复制

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

    2024年02月04日
    浏览(28)
  • (链表) 143. 重排链表 ——【Leetcode每日一题】

    难度:中等 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L 0 L_0 L 0 ​ → L 1 L_1 L 1 ​ → … → L n − 1 L_{n-1} L n − 1 ​ → L n L_n L n ​ 请将其重新排列后变为: L 0 L_0 L 0 ​ → L n L_n L n ​ → L 1 L_1 L 1 ​ → L n − 1 L_{n-1} L n − 1 ​ → L 2 L_2 L 2 ​ → L n − 2 L_{n-2} L n −

    2024年02月08日
    浏览(48)
  • 每日一题(相交链表 )

    欢迎大家来我们主页进行指导 LaNzikinh-CSDN博客 160. 相交链表 - 力扣(LeetCode) 给你两个单链表的头节点  headA  和  headB  ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回  null  。 图示两个链表在节点  c1  开始相交 : 题目数据  保证  整

    2024年04月11日
    浏览(33)
  • 每日一题 206反转链表

    给你单链表的头节点  head  ,请你反转链表,并返回反转后的链表。 示例 1: 示例 2: 示例 3:

    2024年02月13日
    浏览(61)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包