题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
方法一:
思路:
1. 把复制的结点链接在原始链表的每一对应结点后面
2. 把复制的结点的random指针指向被复制结点的random指针的下一个结点
3. 拆分成两个链表,奇数位置为原链表,偶数位置为复制链表,注意复制链表的最后一个结点的next指针不能跟原链表指向同一个空结点None,next指针要重新赋值None(判定程序会认定你没有完成复制)
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
if not pHead:
return None
dummy = pHead
# first step, N' to N next
while dummy:
dummynext = dummy.next
copynode = RandomListNode(dummy.label)
copynode.next = dummynext
dummy.next = copynode
dummy = dummynext
dummy = pHead
# second step, random' to random'
while dummy:
dummyrandom = dummy.random
copynode = dummy.next
if dummyrandom:
copynode.random = dummyrandom.next
dummy = copynode.next
# third step, split linked list
dummy = pHead
copyHead = pHead.next
while dummy:
copyNode = dummy.next
dummynext = copyNode.next
dummy.next = dummynext
if dummynext:
copyNode.next = dummynext.next
else:
copyNode.next = None
dummy = dummynext
return copyHead
方法二:递归
代码:
class Solution:
def Clone(self, head):
if not head: return
newNode = RandomListNode(head.label)
newNode.random = head.random
newNode.next = self.Clone(head.next)
return newNode
方法三:哈希表
代码:
class Solution:
def Clone(self, head):
nodeList = [] #存放各个节点
randomList = [] #存放各个节点指向的random节点。没有则为None
labelList = [] #存放各个节点的值
while head:
randomList.append(head.random)
nodeList.append(head)
labelList.append(head.label)
head = head.next
#random节点的索引,如果没有则为1
labelIndexList = map(lambda c: nodeList.index(c) if c else -1, randomList)
dummy = RandomListNode(0)
pre = dummy
#节点列表,只要把这些节点的random设置好,顺序串起来就ok了。
nodeList=map(lambda c:RandomListNode(c),labelList)
#把每个节点的random绑定好,根据对应的index来绑定
for i in range(len(nodeList)):
if labelIndexList[i]!=-1:
nodeList[i].random=nodeList[labelIndexList[i]]
for i in nodeList:
pre.next=i
pre=pre.next
return dummy.next
方法四:
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
head = pHead
p_head = None
new_head = None
#头结点
random_dic = {}
old_new_dic = {}
while head:
node = RandomListNode(head.label)
#这道题还有一个要求就是不能用节点引用,一定要创建新的节点
#复制原节点的label到新的链表中
node.random = head.random
#复制原节点的随机指针到新的链表中
old_new_dic[id(head)] = id(node)
#创建字典,以原节点的内存地址作为key,新节点的内存地址作为value
random_dic[id(node)] = node
#创建另一个字典,以新节点的地址作为key,新节点作为value
head = head.next
#将head指向下一个节点
if new_head:
new_head.next = node
new_head = new_head.next
#给新链表
else:
new_head = node
p_head = node
#当新链表为空时,为新链表的头结点赋值,这里比较巧妙的就是phead可以作为头结点,而new_head可以放心
#向后移动
new_head = p_head
while new_head:
if new_head.random != None:
new_head.random = random_dic[old_new_dic[id(new_head.random)]]
#这里的问题就是old_new_dic中就没有id(new_head.random])的键,
#因为old_new_dic中的键是原节点的地址,但是这里以新节点的随机节点指针指向了
#一个随机的节点,这样的话,随机节点也是原节点中的,因此,这根据随机节点找到对应的新节点的内存地址了,
#然后通过random_dic就找到了新节点了
new_head = new_head.next
#这个循环的目的就是找到new_head的random属性
#现在又出现一个问题,在上边,不是已经把head.random赋给了new_head.random吗?
#那么进一步推理,存在一种可能,那就是前边并没有给new_head赋予属性random
return p_head
---------------------
作者:我是巴菲特
来源:CSDN
原文:https://blog.csdn.net/weixin_38246633/article/details/80813126
版权声明:本文为博主原创文章,转载请附上博文链接!