入门级题解138. 复制带随机指针的链表

题目解读
复制链表,这个链表带随机指针
https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/fu-zhi-dai-sui-ji-zhi-zhen-de-lian-biao-c2nvs/
思路
不是很会,找到一个很清晰的题解:

这里是引用(迭代) O(n)O(n)

题目要求我们复制一个长度为 n 的链表,该链表除了每个节点有一个指针指向下一个节点外,还有一个额外的指针指向链表中的任意节点或者null,如下图所示:
在这里插入图片描述

如何去复制一个带随机指针的链表?

首先我们可以忽略 random 指针,然后对原链表的每个节点进行复制,并追加到原节点的后面,而后复制 random
指针。最后我们把原链表和复制链表拆分出来,并将原链表复原。

图示过程如下:

1、在每个节点的后面加上它的复制,并将原链表和复制链表连在一起。
在这里插入图片描述

2、 从前往后遍历每一个原链表节点,对于有 random 指针的节点 p,我们让它的 p->next->random = p->random->next,这样我们就完成了对原链表 random 指针的复刻。

在这里插入图片描述

3、最后我们把原链表和复制链表拆分出来,并将原链表复原。

在这里插入图片描述

具体过程如下:
1、定义一个 p 指针,遍历整个链表,复制每个节点,并将原链表和复制链表连在一起。
2、再次遍历整个链表,执行p->next->random = p->random->next,复制random 指针。
3、定义虚拟头节点 dummy,用来指向复制链表的头节点, 将两个链表拆分并复原原链表。

 class Solution { public:
>     Node* copyRandomList(Node* head) {
>         for(auto p = head; p; p = p->next->next)  //复制每个节点,并将原链表和复制链表连在一起。
>         {
>             auto q = new Node(p->val);
>             q->next = p->next;
>             p->next = q;
>         }
> 
>         for(auto p = head; p; p = p->next->next)   //复制random指针
>         {
>             if(p->random)
>               p->next->random = p->random->next;
>         }
> 
>         //拆分两个链表,并复原原链表
>         auto dummy = new Node(-1), cur = dummy; 
>         for(auto p = head; p; p = p->next)
>         {
>             auto q = p->next;
>             cur = cur->next = q;
>             p->next = q->next;
>         }
> 
>         return dummy->next;
>     } };

作者:lin-shen-shi-jian-lu-k
链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer/solution/fu-zhi-dai-sui-ji-zhi-zhen-de-lian-biao-c2nvs/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

收获
1.https://www.cnblogs.com/KunLunSu/p/7861330.html讲auto的用法,就是替代数据类型。
2.` for(auto p = head; p; p = p->next->next) //复制每个节点,并将原链表和复制链表连在一起。
3.

for(auto p = head; p; p = p->next->next)  //复制每个节点,并将原链表和复制链表连在一起。
>         {
>             auto q = new Node(p->val);
>             q->next = p->next;
>             p->next = q;
>         }
  1. p = 1 2 3 4 5 auto p = head
  2. q = 1 auto q = new Node(p->val);
  3. q = 1 2 3 4 5 q->next = p->next;
  4. p = 1 1 2 3 4 5 p->next = q;
  5. p = 2 3 4 5 p = p->next->next
for(auto p = head; p; p = p->next->next)   //复制random指针
>         {
>             if(p->random)
>               p->next->random = p->random->next;
>         }
  1. p = 1 1 2 2 3 3 4 4 5 5
  2. 如果当前节点存在random,p->next->random = p->random->next;
    在这里插入图片描述

把random指向的节点给复制的新节点

 auto dummy = new Node(-1), cur = dummy; 
>         for(auto p = head; p; p = p->next)
>         {
>             auto q = p->next;
>             cur = cur->next = q;
>             p->next = q->next;
>         }
> 
>         return dummy->next;

cur = cur->next = q;

cur->next = q;
cur = cur->next;
  1. p = 1 1 2 2 3 3 4 4 5 5
  2. q = 1 2 2 3 3 4 4 5 5 q = p->next;
  3. cur = 0 1 2 2 3 3 4 4 5 5 cur->next = q;
  4. cur = 1 2 2 3 3 4 4 5 5 cur= cur->next;
  5. p = 1 2 2 3 3 4 4 5 5 p ->next =q->next;
  6. p = 2 2 3 3 4 4 5 5 p = p->next
  7. q = 2 3 3 4 4 5 5
  8. cur = 1 2 3 3 4 4 5 5
  9. cur = 2 3 3 4 4 5 5
  10. p = 2 3 3 4 4 5 5
  11. p = 3 3 4 4 5 5
  12. dummy = 0 1 2 3 4 5
  13. return dummy->next;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值