题目描述:
输入一个复杂链表(每个结点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的结点引用,否则判题程序会直接返回空)
思路:
复制单纯的单链表很容易,根据题目描述主要需要考虑每个结点的随机指针,即每个结点random的指向。。
-
暴力求解:先遍历列表同时记录val和random域的值,分别存放在val_list和random_list中,然后首先使用val_list中的元素依次新建结点并设置next构成基本链。然后构建两个指针 和 ,其中 指向当前结点, 用于搜索random指向的结点。接着从新链第一个节点 开始,看它在random_list中是否有值,如果有,从头遍历链表,直到找到val为指定值的结点,将当前结点的random指向它,同时将 指向下一个位置, 回到头结点。不断遍历,直到 为止。但这样的算法复杂度为 ,在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指向的操作,因此时间复杂度为 。
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