【题目描述】
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
【思路一】
将链表完全复制,那么每个节点都将开辟一个新的空间。如果没有random指针,那非常容易复制,因为可以很容得找到节点的前后关系。但是由于加入了random指针,原来节点为oldnode=【A,B,C,D】,复制节点为newnode=[a,b,c,d],加入A.random是C,那么在复制节点中找到,要实现a.random就要找到c。
如何能找到c呢?就需要从复制链表的头开始找,对比值,找到与C值相同的c,找一次O(n),每个节点的random都这样寻找的话,时间复杂度就是O(n*n).如果我们能够建立一个字典,找到对应关系,就可以免去找点的过程。
字典dic,dic[0]=2代表着newnode[0],即a的random就是newnode[2],即c。建立了映射关系将时间复杂度降低为线性的。
【代码一】
python:
class Solution:
def Clone(self, phead):
if not phead:
return None
pnode=phead
dic={}
node_list=[]
while(pnode):
node_list.append(pnode)
pnode=pnode.next
pnode=phead
while(pnode):
if(pnode.random):
dic[node_list.index(pnode)]=node_list.index(pnode.random)
else:
dic[node_list.index(pnode)]=None
pnode=pnode.next
newnode=[RandomListNode(node.label) for node in node_list]
for i,node in enumerate(newnode):
if(i<len(newnode)-1):
newnode[i].next=newnode[i+1]
if(dic[i]):
newnode[i].random=newnode[dic[i]]
return newnode[0]
【思路2】
也是书中的思路,三步走: A-B-C a-b-c
1.复制节点插在每个原始节点后:A-a-B-b-C-c
2.给复制节点找random指针,pnode,newnode;这次newnode.random=pnode.random.next
3.拆成两个链表,返回复制链表头节点
这样做,节约了空间复杂度,无需额外空间。所以说,这种方式的时间复杂度为O(n),空间复杂度O(1)
【代码】
class Solution:
def Clone(self, phead):
if not phead:
return None
self.func1(phead)
self.func2(phead)
return self.func3(phead)
def func1(self,phead):
pnode=phead
while(pnode):
clonenode=RandomListNode(pnode.label)
clonenode.next=pnode.next
pnode.next=clonenode
pnode=clonenode.next
def func2(self,phead):
pnode=phead
while(pnode):
if(pnode.random):
pnode.next.random=pnode.random.next
pnode=pnode.next.next
def func3(self,phead):
pnode=phead
if(pnode):
newhead=pnode.next
newnode=newhead
pnode.next=newnode.next
pnode=pnode.next
while(pnode):
newnode.next=pnode.next
newnode=newnode.next
pnode.next=newnode.next
pnode=pnode.next
return newhead