返回

剖析 LeetCode 138:揭秘复制带随机指针的链表

前端

复制带随机指针的链表:剖析 LeetCode 138

在链表操作的广阔领域中,复制带随机指针的链表是一个颇具挑战性的难题。随机指针打破了链表节点之间的常规连接,迫使我们寻找间接的方法来复制结构。本文将深入探讨 LeetCode 138 问题,逐步揭示如何巧妙地应对这一复杂的任务。

理解问题

LeetCode 138 要求我们复制一个链表,同时保持其随机指针关系。所谓随机指针,是指向链表中任何节点的指针。这意味着仅仅复制节点数据是不够的,我们还必须保留它们相互连接的方式。

打破直接联系:哈希表的引入

复制链表的关键在于打破节点之间的直接联系。我们不能直接复制链表,因为这会破坏原始链表的结构。取而代之的是,我们使用哈希表来存储原始节点与新创建的副本节点之间的映射关系。哈希表通过键值对存储信息,原始节点作为键,复制节点作为值。

逐个复制节点

一旦我们建立了哈希映射,就可以逐个复制原始链表中的节点。对于每个原始节点,我们创建一个新的节点,并将其值复制到新节点中。接下来,我们使用哈希表查找原始节点的随机指针,并将其作为新节点的随机指针。

连接新节点:构建新链表

最后,我们连接新节点以形成新链表。对于每个原始节点,我们设置其复制节点的 next 指针指向复制节点的下一个节点,并设置其复制节点的 random 指针指向复制节点的随机指针。通过这种方式,我们构建了一个与原始链表具有相同结构和随机指针关系的新链表。

代码示例

def copy_random_list(head):
    # 创建哈希表,存储原始节点和复制节点的映射
    hash_table = {}

    # 创建新链表的头部节点
    new_head = ListNode(head.val)

    # 初始化两个指针:old_ptr 遍历原始链表,new_ptr 遍历新链表
    old_ptr = head
    new_ptr = new_head

    # 逐个复制节点,同时建立哈希映射
    while old_ptr:
        # 创建新节点,并将其添加到哈希表中
        new_node = ListNode(old_ptr.val)
        hash_table[old_ptr] = new_node

        # 将新节点连接到新链表中
        new_ptr.next = new_node

        # 更新两个指针
        old_ptr = old_ptr.next
        new_ptr = new_ptr.next

    # 更新随机指针
    for old_node, new_node in hash_table.items():
        if old_node.random:
            new_node.random = hash_table[old_node.random]

    # 返回新链表的头部节点
    return new_head

结论

复制带随机指针的链表是一种复杂但重要的技术,它需要打破链表中的直接联系并巧妙地使用哈希表。通过逐个复制节点并连接它们,我们可以创建一份独立的新链表,同时保留原始链表的随机指针关系。掌握这一技术对于解决各种数据结构问题至关重要。

常见问题解答

1. 为什么我们需要使用哈希表?

哈希表允许我们间接地连接原始节点和复制节点,从而打破链表中的直接联系,避免破坏原始链表的结构。

2. 如何处理随机指针为空的情况?

如果原始节点的随机指针为空,我们将其复制节点的随机指针也设置为 null。

3. 如何确保新链表和原始链表具有相同的顺序?

通过按顺序逐个复制节点,我们可以确保新链表和原始链表具有相同的顺序。

4. 是否可以使用其他数据结构来解决这个问题?

除了哈希表之外,还可以使用数组或字典来存储原始节点和复制节点之间的映射关系。

5. 复制带随机指针的链表在实际应用中有什么好处?

复制带随机指针的链表技术用于处理具有复杂连接关系的数据结构,例如图和DAG(有向无环图)。