输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
# -*- 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