【剑指offer】复杂链表的复制 python

323 阅读2分钟

【题目描述】

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的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