剑指offer - 复杂链表的复制 - python

题目描述:

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

思路

复制单纯的单链表很容易,根据题目描述主要需要考虑每个结点的随机指针,即每个结点random的指向。。

  • 暴力求解:先遍历列表同时记录val和random域的值,分别存放在val_list和random_list中,然后首先使用val_list中的元素依次新建结点并设置next构成基本链。然后构建两个指针 p p r r ,其中 p p 指向当前结点, r r 用于搜索random指向的结点。接着从新链第一个节点 n e w H e a d . n e x t newHead.next 开始,看它在random_list中是否有值,如果有,从头遍历链表,直到找到val为指定值的结点,将当前结点的random指向它,同时将 p p 指向下一个位置, r r 回到头结点。不断遍历,直到 p . n e x t = = N o n e p.next == None 为止。但这样的算法复杂度为 O ( n 2 ) O(n^2) ,在OJ平台上会发生时间超出的错误。

  • 聪明的求法:先依次复制给定链表的结点构成新链然后再断链得到原始链表的复制,具体的过程如下所示:


    在这里插入图片描述

​假设初始链表如(1)所示,链表中包含1、2、3、4四个结点,结点的random指向分别为:

1.random = 3
2.random = 2 
3.random = 4 
4.random = 2

​首先,复制每个结点将其链接在它后面构成如(2)所示的新链:

cur = pHead
# 始终保证cur指向原始链表中的结点
while cur:
    node = RandomListNode(cur.label)
    # 在原始链中插入
    node.next = cur.next
    cur.next = node
    cur = node.next

得到插入复制结点后的新链表后,我们还需要设置新结点的random,使其和它和给定链表中的结点一致:

cur = pHead
while cur:
    # 可能某些结点的random为None,因此先进行判断
    if cur.random:
        cur.next.random = cur.random.next
        
     # # 始终保证cur指向原始链表中的结点
     cur = cur.next.next

​经过上述步骤,新链表的中每个结点的next和random都指向了正确的结点,但这样的链表不是我们想要的。由于不能直接返回给定链表的头结点,我们需要从新链表中将复制的节点抽出来,同时保证抽出的结点的next和random指向和最开始的链表一致。


在这里插入图片描述

cur = pHead
# 指向复制结点中的第一个结点,只用于输出
newHead = pHead.next
# 指向复制结点中的第一个结点,用于断链
new_cur = pHead.next

while cur:
    # 断开原链表中的结点和复制结点的next指向,将next指向原链表中的对应结点,即next.next
    cur.next = cur.next.next
    # 看是否遍历完了所有的结点
    if new_cur.next:
        # 类似上一步
        new_cur.next = new_cur.next.next
        # 由于此时new_cur指向的结点的next已经发生了改变,因此只需要将next后移即可
        new_cur = new_cur.next
        
    # 类似new_cur的上一步操作
    cur = cur.next

​ 最终newHead作为头结点的链表就是复制后的链表,即我们想要的结果。由于在复制完结点后所做的只是结点next和random指向的操作,因此时间复杂度为 O ( n ) O(n)


AC代码

# -*- 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
        if pHead == None:
            return None

        cur = pHead
        while cur:
            node = RandomListNode(cur.label)
            node.next = cur.next
            cur.next = node
            cur = node.next
             
        cur = pHead
        while cur:
            if cur.random:
                cur.next.random = cur.random.next
            cur = cur.next.next

        cur = pHead
        newHead = pHead.next
        new_cur = pHead.next
        
        while cur:
            cur.next = cur.next.next
            if new_cur.next:
                new_cur.next = new_cur.next.next
                new_cur = new_cur.next

            cur = cur.next
          
        return newHead

暴力求解[不一定对哦]

# -*- 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
        if pHead == None:
            return None
        
        cur = pHead.next
        list_ele = []
        random_ele = []
        while cur:
            list_ele.append(cur.label)
            if cur.random:
                random_ele.append(cur.random.label)
            else:
                random_ele.append(None)
            cur = cur.next
        
        newHead = RandomListNode(-1)
        p = newHead
        for i in list_ele:
            node = RandomListNode(i)
            p.next = node
            p = p.next
            
        pp = newHead.next
        r = newHead.next
        index = 0
        while pp:
            randomEle = random_ele[index]
            index += 1
            if randomEle != None:
                while r:
                    if r.label == randomEle:
                        pp.random = r
                        r = newHead.next
                    else:
                        r = r.next
                
            pp = pp.next
        return newHead 

还有一种投机的方法,直接使用copy库的deepcopy函数进行复制,额……

# -*- coding:utf-8 -*-
# class RandomListNode:
#     def __init__(self, x):
#         self.label = x
#         self.next = None
#         self.random = None
import copy
class Solution:
    # 返回 RandomListNode
    def Clone(self, pHead):
        ret = copy.deepcopy(pHead)
        
        return ret
发布了295 篇原创文章 · 获赞 103 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/Forlogen/article/details/104883569
今日推荐