复制带随机指针的链表
难度 中等
题目
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
- val:一个表示 Node.val 的整数。
- random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
你的代码只接受原链表的头节点 head 作为传入参数。
注意:这里的random指的是节点的地址,random_index才是索引值,对于具体的地址值我们可以用一个指针指向该节点,则该指针指的就是该节点的地址
示例1
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例2
输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例3
输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例4
输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
解题思路:在每个原节点后面复制节点
此题的难点在于随机指针的复制,若直接取出原节点的随机指针的值进行赋值,则取出的为地址,那么复制的节点随机指针指的就是同一地址,指的就是原链表的节点了,所以不能直接取出进行复制。我们可以根据链表节点的关系,定义指针来进行指向
- 在每个原节点后面复制原节点构成新的链表(A—>A’–>B–>B’–>C–>C’)
- 对新的链表进行遍历,并进行随机指针的指向复制。定义指针p指向头节点A,若p.random存在并指向B,则A’.random应指向B’,则有p.next.random指向p.random.next
- 对链表(A—>A’–>B–>B’–>C–>C’)进行拆分,将复制的节点从原链表中拆除并串成新的链表(A’–>B’–>C’)
代码
class Node:
def __init__(self, x, next=None, random=None):
self.val = int(x)
self.next = next
self.random = random
class Solution(object):
def copyRandomList(self, head):
"""
:type head: Node
:rtype: Node
"""
if head is None:
return
p = q = head
# 在每个原节点后面复制节点
while head:
node = Node(head.val, None, None)
node.next = head.next
head.next = node
head = head.next.next
# 拷贝随机指针
while p:
if p.random
p.next.random = p.random.next
p = p.next.next
# 将复制的节点从原链表中拆除
r = Node(0, None, None)
cur = r
while q:
r.next = q.next
q.next = r.next.next
q = q.next
r = r.next
return cur.next
至此,此题解答完毕
此题还可以用哈希表来做,等到后面的哈希表我再写