1、题目描述
https://leetcode-cn.com/problems/copy-list-with-random-pointer/
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的 深拷贝。
我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
- val:一个表示 Node.val 的整数。
- random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
2、代码详解
python3版代码
时间复杂度:O(N) 空间复杂度:O(1)
(1)遍历原来的链表并拷贝每一个节点,将拷贝节点放在原来节点的旁边,创造出一个旧节点和新节点交错的链表。
(2)迭代这个新旧节点交错的链表,并用旧节点的 random 指针去更新对应新节点的 random 指针。比方说, B 的 random 指针指向 A ,意味着 B' 的 random 指针指向 A'
(3)现在 random 指针已经被赋值给正确的节点, next 指针也需要被正确赋值,以便将新的节点正确链接同时将旧节点重新正确链接。
"""
# Definition for a Node.
class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = int(x)
self.next = next
self.random = random
"""
class Solution:
def copyRandomList(self, head: 'Node') -> 'Node':
if not head:
return head
# 1)遍历原来的链表并拷贝每一个节点,将拷贝节点放在原来节点的旁边,创造出一个旧节点和新节点交错的链表
cur = head
while cur is not None:
next = cur.next
node = Node(cur.val) # 加入 复制节点,复制结点紧靠原结点
node.next = cur.next
cur.next = node
cur = next # 原节点 后移
copy = head.next # 复制后的头结点
# 2)迭代这个新旧节点交错的链表,并用旧节点的 random 指针去更新对应新节点的 random 指针
# 先同步随机结点引用(random 指针 赋值给正确的节点)
pre = head
while pre is not None:
if pre.random:
pre.next.random = pre.random.next # B 的 random 指针指向 A ,意味着 B' 的 random 指针指向 A'
else:
pre.next.random = None
pre = pre.next.next
# 3)next 指针也需要被正确赋值,以便将新的节点正确链接同时,将旧节点重新正确链接。
# 再还原结点顺序指向
pre = head
while pre is not None:
next = pre.next.next # B
if next is not None:
pre.next.next = next.next # A' -> B'
else:
pre.next.next = None
pre = next # A -> B
return copy