每日一题(复制带随机指针的链表)

简介: 每日一题(复制带随机指针的链表)

每日一题(复制带随机指针的链表)


138. 复制带随机指针的链表 - 力扣(LeetCode)


a3ae6dd7a9e122ba676f866deb69e53e_8ed4e12d881946368f593a4a8ce71fbe.png


思路:


由于每个链表还包含了一个random节点指向了链表中的随机节点,所以并不能直接照搬复制原链表。首先想到的暴力思路是复制一条新的链表。找到原链表的每个节点的random到该节点的相对举例。但是实际上操作起来更复杂。


这里提供另外一个思路:


  • 第一步:创建新节点

在原链表的每个节点之后紧跟着复制一个节点,形成新老节点相间的局面,并且将原链表的每个节点的值赋值给其后创建的节点中,并且将新开辟的节点的random成员的值设置为NULL,如下图:

deff64c4ca939517870d90b93b2069ad_5ef6fdb80e8a44eea7b3f9afc3a844a6.png



  • 第二步:设置新节点random的值

创建一个cur指针指向原链表的第一个节点,再创建一个newhead指针指向cur的next;cur指针从head处出发,newhead从head->next处出发。开始遍历链表。这里有一个最重要的关系:当cur->random不为空时,(当cur->random的值为NULL时,则不做改动)满足:cur->random与cur的对应关系与newhead->random和cur->random->next的对应关系时一样的。


就可以根据这些对应关系修改新创建的节点的random的值。接着cur向后移动两步指向下一个原链表中的节点,newhead也向后走两步指向下一个新开辟的节点。如下图所示(红色的是random指针,绿色的是next指针):新节点之间的random的链接关系和原链表的random的链接关系并没有改变。

7cdce1a36a313de12c02df94607ba4d9_28d64aa891ce4b87aa21a64154f31021.png


  • 第三步:断开链表

创建三个指针cur1和cur2和newhead,cur1从head的next处开始遍历,cur2从head处开始遍历,newhead指针用于记录cur1的起始位置。将原链表的节点和新链表的节点各自分成一条链表。特别注意:这里的遍历迭代的顺序不得交换! 在两个指针向后更新的过程中,肯定是cur1->next先为NULL,当cur1->next为NULL时就退出循环,但是此时的cur2的next指针仍然指向的是新开辟的最后一个节点。所以在返回newhead之前,要将cur2->next置为NULL。

1decc96244f11bbd3e7710005901f303_7af95de5e06b4b84a4ca66f23cc5bdbe.png


代码实现:


  if(head==NULL)
    {
        return NULL;
    }
    struct Node* cur = head;
    struct Node* curNext = head;
    struct Node* newhead = head;
    //构造相间的节点
    while(cur!=NULL)
    {
        curNext = cur->next;
        struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
        if(newnode== NULL)
         return NULL;
        newnode->val = cur->val;
        newnode->random =NULL;
        //新节点链接在原节点之后
        cur->next = newnode;
        newnode->next = curNext;
        cur = curNext;
    }
    cur = head;
    //复制各自的random
    while(cur!=NULL)
    {
        newhead = cur->next;
        if(cur->random!=NULL)
        {
            newhead->random = cur->random->next;
        }
        cur = cur->next->next;
    }
    //断开
    newhead = head->next;
    struct Node* cur1 = newhead;//cur1用于遍历newnode
    struct Node* cur2 = head;//cur2用于遍历原链表的节点
    while(cur1->next)
    {
        cur2->next = cur2->next->next;
        cur1->next = cur1->next->next;
        cur2 = cur2->next;       
        cur1 = cur1->next;
    }
  //将cur2->next置空
    cur2->next = NULL;
    return newhead;


完结


复制带随机指针的链表习题的分析就到这里啦,若有不足,欢迎评论区指正,下期见!


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