数据结构(剑指offer)(复杂链表的复制)(python)

题目描述 
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的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 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/weixin_41643439/article/details/87207319
今日推荐