首页 > 其他分享 >LeetCode138 复制带随机指针的链表

LeetCode138 复制带随机指针的链表

时间:2022-10-06 23:23:12浏览次数:83  
标签:Node 结点 random head next 链表 LeetCode138 NULL 指针

 

idea:  刚开始没有思路,被题目弄懵了,我能想到的方法就是先复制不带random指针的链表,之后由表头到表尾再将每个结点的random指针通过循环进行连接,时间复杂度肯定时很高的,具体代码也没有

实现。之后看到题解,经过就牛二虎之力也是堪堪看懂。

idea 之题解: 见注释,也是看了好半天才把注释写出来。整体思路是利用递归的思想解决如何复制带有两个指针的结点,将当前结点两个指针指向结点的复制工作分开来完成,写成两条语句,进而解决了问题。期间,利用哈希表快速找到原random指针指向结点的映射。

法一: 递归+哈希表

/* // Definition for a Node. class Node { public:     int val;     Node* next;     Node* random;          Node(int _val) {         val = _val;         next = NULL;         random = NULL;     } }; */
class Solution { public:     unordered_map<Node*, Node*> newList;        //建立哈希表用于储存新建结点,防止重复生成同一结点     Node* copyRandomList(Node* head) {         if(head == nullptr){        //判断传入结点是否为空             return nullptr;         }         if( !newList.count(head) ){         //检查结点是否已存在,或者已经被建立过             Node* headNew = new Node(head->val);    //给新建结点赋值             newList[head] = headNew;        //newhead为原表head结点的映射,或者说新建表中newhead为原表head的实时替身             headNew->next = copyRandomList(head->next);     //递归依次生成新表的各个next结点,直到表尾             //该条语句作用原理:新表与原表同步位移,通过生成对应next结点的替身接到新表的结点完成任务             headNew->random = copyRandomList(head->random);      //在上一条语句回溯过程中,该条语句开始产生作用,上一条语句每一次回溯,该条语句开始为当前结点生成其random指针指向的结点,由于经由上一条语句递归作用后新表每一个结点的next指针指向的结点都已设置好,所以该语句直接返回原表相同位置结点的替身结点,不发生递归         }         return newList[head];     //对应替身结点已存在,则直接返回     } };  

复杂度分析

时间复杂度:O(n)O(n),其中 nn 是链表的长度。对于每个节点,我们至多访问其「后继节点」和「随机指针指向的节点」各一次,均摊每个点至多被访问两次。

空间复杂度:O(n)O(n),其中 nn 是链表的长度。为哈希表的空间开销。

 

 法二:迭代+结点拆分       idea:方法太巧妙了。直接复制结点,并直接连接到原表中,形成A-A`-B-B`-C-C`的情况,此时A`的random指向的结点为A->random->next,巧妙的解决了random指针的问题

 

/* // Definition for a Node. class Node { public:     int val;     Node* next;     Node* random;          Node(int _val) {         val = _val;         next = NULL;         random = NULL;     } }; */
class Solution { public:     Node* copyRandomList(Node* head) {         if(head==NULL){     //检查是否为空链表             return NULL;         }         for(Node*p=head; p!=NULL; p=p->next->next){      //循环复制每一个结点,并插入到其后             Node*newnode=new Node(p->val);      //复制结点             newnode->next=p->next;              //插入操作             p->next=newnode;         }         for(Node*p=head; p!=NULL; p=p->next->next){         //循环为替身节点配置random指针,为原random的后继结点             p->next->random = p->random == NULL ? NULL : p->random->next;         }         Node* newhead = head->next;             //保存新表头结点         for(Node* p=head; p!=NULL; p=p->next){          //将新表从原表中脱离出来             Node* newnode=p->next;             p->next = p->next->next;                         newnode->next = newnode->next == NULL ? NULL :newnode->next->next;      //到表尾时后附null,防止出现null->next情况         }         return newhead;     } };

 

 

复杂度分析

时间复杂度:O(n)O(n),其中 nn 是链表的长度。我们只需要遍历该链表三次。

读者们也可以自行尝试在计算拷贝节点的随机指针的同时计算其后继指针,这样只需要遍历两次。
空间复杂度:O(1)O(1)。注意返回值不计入空间复杂度。

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

 


TRANSLATE with x English
Arabic Hebrew Polish
Bulgarian Hindi Portuguese
Catalan Hmong Daw Romanian
Chinese Simplified Hungarian Russian
Chinese Traditional Indonesian Slovak
Czech Italian Slovenian
Danish Japanese Spanish
Dutch Klingon Swedish
English Korean Thai
Estonian Latvian Turkish
Finnish Lithuanian Ukrainian
French Malay Urdu
German Maltese Vietnamese
Greek Norwegian Welsh
Haitian Creole Persian  
  TRANSLATE with COPY THE URL BELOW Back EMBED THE SNIPPET BELOW IN YOUR SITE Enable collaborative features and customize widget: Bing Webmaster Portal Back

标签:Node,结点,random,head,next,链表,LeetCode138,NULL,指针
From: https://www.cnblogs.com/Ting-LOVE/p/16758813.html

相关文章

  • 链表----相关概念
    1.结点:一个数据域一个指针域2.链表:顺序表的链式存储3.单链表、双链表、循环链表:结点只有一个指针域的链表,称为单链表或者线性链表结点有两个指针域的链表,称为双链......
  • 关于指针的心得2-结构体指针
    结构体指针:1、指针的类型是结构体,也就是说指针只能指向结构体,同时,如果想用其他指针指向结构体则必须实现类型的强制转换 2、结构体指针的基本操作①如果想用结构......
  • 链表中间节点
    slow一次走一步,fast一次走两步。那么当fast到达链表的末尾时,slow必然位于中间。ListNode*middleNode(ListNode*head){ListNode*slow=head;......
  • 反转链表
    ListNode*reverseList(ListNode*head){ListNode*tail=NULL;ListNode*front=head;ListNode*curr=NULL;//先令curr指向front,fro......
  • 合并链表
    ListNode*mergeTwoLists(ListNode*l1,ListNode*l2){if(l1==NULL){if(l2==NULL){returnNULL;}els......
  • 关于指针的心得1
    1、%p对于任何类型的变量都适用,显示的都是他的地址。但是在使用之前必须保证他是个地址(加上取址符号&);2、指针就是地址,每个地址对应着八个比特大小的空间或者说一个字节;3......
  • 剑☞offer 两个链表的第一个公共节点
    题目描述:给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。题目数据 保证 整个链式结构中不存......
  • 力扣138(java)- 复制带随机指针的链表(中等)
    题目:给你一个长度为n的链表,每个节点包含一个额外增加的随机指针random,该指针可以指向链表中的任何节点或空节点。构造这个链表的 深拷贝。 深拷贝应该正好由n个......
  • LeetCode 10 - 双指针
    11.盛最多水的容器方法:双指针用两个指针指向「容器」的左右边界,每次移动数字较小那一侧的指针,直到两指针相遇。这样移动指针的正确性是可以保证的。publicintmaxAre......
  • LeetCode 03 - 链表
    707.设计链表设计链表的实现,您可以选择使用单链表或双链表。在链表类中实现这些功能:get(index):获取链表中第index个节点的值。如果索引无效,则返回1。addAtHead(val......