Skip to main content

138.复制带随机指针的链表

标签: linked-list, hash-table

难度: Medium

通过率: 58.67%

原题链接: https://leetcode.com/problems/copy-list-with-random-pointer/description/

题目描述

给定一个长度为 nn 的链表,其中每个节点包含一个额外的随机指针,指向链表中的任意节点或 nullnull。构造链表的深拷贝。深拷贝应该由正好 nn 个全新节点组成,其中每个新节点的值设置为其对应的原始节点的值。新节点的 nextnextrandomrandom 指针应该指向复制链表中的新节点,使得原始链表和复制链表中的指针对应于相同的列表状态。在新列表中,不能有指针指向原始列表中的节点。

解题思路

要解决这个问题,通常我们需要三个步骤:

  1. 复制节点并插入到原始节点之后:

    • 遍历链表,对于每个原始节点,创建一个新节点,并将它插入到原始节点的后面。这样,新列表和旧列表的组合将交错在一起。
  2. 设置新节点的随机指针:

    • 再次遍历链表,通过 original.next.random=original.random.nextoriginal.next.random = original.random.next 来设置新节点的随机指针。
  3. 将交错的链表分离:

    • 最后一个遍历,通过跳转访问(让每个节点的 nextnext 指针跳过一个节点)来恢复原始链表并取出复制链表。

代码实现

class Node:
def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
self.val = x
self.next = next
self.random = random

class Solution:
def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
if not head:
return None

# Step 1: 复制节点并插入到原始节点之后
current = head
while current:
copy = Node(current.val, current.next)
current.next = copy
current = copy.next

# Step 2: 设置新节点的随机指针
current = head
while current:
if current.random:
current.next.random = current.random.next
current = current.next.next

# Step 3: 分离链表
current = head
pseudo_head = Node(0)
copy_current = pseudo_head
while current:
copy = current.next
copy_current.next = copy
copy_current = copy
current.next = copy.next
current = current.next

return pseudo_head.next

复杂度分析

时间复杂度:O(n)O(n),其中 nn 是链表的节点数。 空间复杂度:O(1)O(1),因为我们只使用了常数空间来存储指针。