当前位置: 首页 > 后端技术 > Python

LeetCode138-CopyListwithRandomPointer

时间:2023-03-26 13:41:52 Python

给定一个链表,每个节点包含一个额外的随机指针,它可以指向链表中的任何节点或一个空节点。请求返回此链表的深层副本。给出一个链表,使得每个节点包含一个额外的随机指针,该指针可以指向列表中的任何节点或null。返回列表的深层副本。示例:输入:{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}解释:节点1的值为1,它的next指针和random指针都指向节点2。节点2的值为2,它的next指针指向null,它的随机指针指向它自己。提示:您必须返回给定标头的副本作为对克隆列表的引用。注意:您必须返回给定头的副本作为对克隆列表的引用。解题思路:由于需要考虑随机指针,所以随机指针指向的节点可能为null,也可能是链表的最后一个节点。深拷贝,不能把新链表的随机指针指向原链表的节点,所以不能一下子得到新链表。解决问题的方法有两种,一种是复制所有节点,暂存在一个数据结构中,然后再次遍历该数据结构,找到复制的节点,确定随机指针的指向。因为每个节点都要找到随机指针指向的节点,如果使用哈希表(字典),查找复杂度为O(1),可以将总时间复杂度降低到O(n),因为所有节点需要暂存,其空间复杂度为O(n)。解决问题的另一种方法是需要遍历三次才能得到结果。简单的说就是先复制每个节点,复制的节点连接到原节点,以此类推。确定随机节点的关系后,对链表进行分裂。这是一个很巧妙的思路:原链表:1->2->3复制每个节点到原节点后面:1->1->2->2->3->3复制随机指针的指向关系子链表:1->2->3,1->2->3复制随机指针时,原节点的随机节点和下一个节点为本链表的随机节点新节点。如果原链表:1->2->3,节点1的随机节点为3,复制节点后:1->1->2->2->3->3我们只需要复制新节点(原节点1的下一个节点)指向原节点的随机节点的下一个节点(原节点的随机节点为3,复制后随机节点3的下一个节点仍为3,但这个节点是一个新节点),最后拆分链表(链表拆分不影响节点指向关系)。它的时间复杂度为O(n),空间复杂度为O(1)。第一种方法:Java:classSolution{publicNodecopyRandomList(Nodehead){if(head==null)returnnull;HashMapmap=newHashMap<>();//用hashMapNodenewHead=newNode(0);//虚拟头节点Nodecur=newHead;//指针指向当前节点Nodetmp;while(head!=null){if(map.containsKey(head)){//查询原节点在map中是否存在tmp=map.get(head);//存在则直接取值}else{tmp=newNode(head.val);//如果不存在,则新建一个具有相同值的节点map.put(head,tmp);//保存在map中,key为原节点,value为新节点}cur.next=tmp;if(head.random!=null){//当原节点的随机节点不为空时if(map.containsKey(head.random)){//查询随机节点是否已经存在于map中tmp.random=map.get(head.random);//如果存在,直接将新节点的随机指针指向它的值}else{tmp.random=newNode(head.random.val);//如果存在不存在,新建一个相同值的随机节点map.put(head.random,tmp.random);//存入map,key为原节点的随机节点,值为新节点的随机节点}}head=head.next;//刷新原链表的当前头节点cur=tmp;//即cur=cur。next,刷新新链表的当前节点}returnnewHead.next;}}Python3:classSolution:defcopyRandomList(self,head:'Node')->'Node':如果不是head:returnNonemap={}newHead=Node(val=0,next=None,random=None)cur=newHeadwhilehead:如果headinmap.keys():tmp=map.get(head)else:tmp=Node(val=head.val,next=None,random=None)map.setdefault(head,tmp)cur.next=tmpifhead.random:如果head.randominmap.keys():tmp.random=map.get(head.random)else:tmp.random=Node(val=head.random.val,下一个=无,随机=无)map.setdefault(head.random,tmp.random)head=head.nextcur=tmpreturnnewHead.next第二种方法:Java:classSolution{publicNodecopyRandomList(Nodehead){if(head==null)returnnull;//复制节点1->2->3==>1->1->1->2->2->3->3节点cur=head;while(cur!=null){节点next=cur.next;节点tmp=新节点(cur.val);cur.next=tmp;tmp.next=下一个;当前=下一个;}//复制随机指针cur=head;while(cur!=null){//cur.next.random=>randomnodefornewnodecur.random.next=>原节点的随机节点的下一个节点cur.next.random=cur.random==空?空:cur.random.next;cur=cur.next.next;//链表翻倍后必须是偶数链表,所以可以直接用cur.next.next}//分离节点cur=head;NodenewHead=head.next;//新链表头节点while(cur!=null){Nodetmp=cur.next;当前next=tmp.next;cur=cur.next;tmp.next=cur==null?空:cur.n分机;}返回新头;}}Python3:classSolution:defcopyRandomList(self,head:'Node')->'Node':如果不是head:returnNonecur=headwhilecur:next=cur.nexttmp=Node(val=cur.val,next=next,random=None)cur.next=tmpcur=nextcur=headwhilecur:cur.next.random=cur.random.nextifcur.randomelseNonecur=cur.next.nextcur=headnewHead=head.nextwhilecur:tmp=cur.nextcur.next=tmp.nextcur=cur.nexttmp.next=cur.nextifcurelseNone返回newHead.Fugo第一次学习:爱照片错误