返回

图解LeetCode——138. 复制带随机指针的链表,轻松掌握副本构建技巧

后端

深度剖析带随机指针的链表复制:LeetCode 138 题解

在计算机科学的广阔领域中,链表作为一种重要的数据结构,以其高效的内存管理和灵活的插入删除操作而著称。然而,当链表元素配备了指向其他链表元素的随机指针时,情况就会变得更加复杂。复制这样的链表是一项充满挑战的任务,需要我们深入理解链表结构和指针操作。

理解题目要点

LeetCode 138 题要求我们复制一个带有随机指针的链表,这意味着新链表中的每个元素不仅需要复制原始元素的值,还需要复制指向原始链表中其他元素的随机指针。为了完成这一任务,我们需要制定一种巧妙的策略,既能高效地复制链表结构,又能准确地维护随机指针之间的对应关系。

哈希表:建立映射关系的桥梁

哈希表是一种数据结构,以其快速查找和插入操作而闻名。在解决 LeetCode 138 题时,哈希表将成为我们建立旧链表元素与新链表元素之间映射关系的桥梁。当我们遍历原始链表时,我们将把每个旧元素作为键,对应的复制元素作为值,存储在哈希表中。

构建新链表:镜像原始结构

有了哈希表的映射关系,我们就可以开始构建新链表了。在这个过程中,我们将逐一复制原始链表中的元素,并利用哈希表来查找和更新新元素的随机指针。通过这种方式,新链表将镜像原始链表的结构和随机指针关系,从而实现深拷贝。

代码示例:揭秘实现细节

为了加深理解,我们提供了两种实现 LeetCode 138 题的代码示例:一种基于迭代,另一种基于递归。

迭代方法:按部就班

def copyRandomList(head):
    if not head:
        return None

    # 创建哈希表记录映射关系
    old_to_new = {}

    # 构建新链表
    new_head = Node(head.val)
    old_to_new[head] = new_head
    curr_old = head.next
    curr_new = new_head

    # 遍历旧链表,构建新链表并记录映射关系
    while curr_old:
        new_node = Node(curr_old.val)
        old_to_new[curr_old] = new_node
        curr_new.next = new_node
        curr_old = curr_old.next
        curr_new = curr_new.next

    # 根据哈希表中的映射关系,更新新链表节点的 random 指针
    curr_old = head
    curr_new = new_head
    while curr_old:
        curr_new.random = old_to_new[curr_old.random]
        curr_old = curr_old.next
        curr_new = curr_new.next

    return new_head

递归方法:拆分与合并

def copyRandomList(head):
    if not head:
        return None

    # 创建哈希表记录映射关系
    old_to_new = {}

    # 构建新链表
    new_head = Node(head.val)
    old_to_new[head] = new_head

    # 使用递归构建新链表并记录映射关系
    def copy(curr_old):
        if not curr_old:
            return None

        if curr_old in old_to_new:
            return old_to_new[curr_old]

        new_node = Node(curr_old.val)
        old_to_new[curr_old] = new_node

        new_node.next = copy(curr_old.next)
        new_node.random = copy(curr_old.random)

        return new_node

    return copy(head)

总结:掌握复杂链表的精髓

LeetCode 138 题为我们提供了一个极好的机会,让我们深入探索链表操作和随机指针处理的奥妙。通过使用哈希表记录映射关系,并结合迭代或递归的方式构建新链表,我们可以高效地复制出带有随机指针的链表的深拷贝。

常见问题解答:深入浅出

  1. 为什么使用哈希表来记录映射关系?
    哈希表的高效查找和插入操作使其成为记录旧链表元素与新链表元素之间映射关系的理想选择。

  2. 迭代方法和递归方法有什么区别?
    迭代方法按部就班地遍历原始链表,而递归方法采用拆分和合并的策略。两种方法都可以有效地复制链表,但迭代方法通常更简单易懂。

  3. 新链表中的随机指针如何更新?
    我们使用哈希表中的映射关系来更新新链表中元素的随机指针,从而确保它们指向正确的新元素。

  4. 时间复杂度和空间复杂度是多少?
    时间复杂度为 O(n),其中 n 是链表中元素的数量。空间复杂度为 O(n),因为我们需要使用哈希表来记录映射关系。

  5. 这道题的变体有哪些?
    LeetCode 138 题的变体可能包括复制带有环或自交叉的链表。解决这些变体需要额外的技巧和算法。