返回

深入解读LeetCode-138:掌握随机指针链表复制的技巧

前端

前言

在计算机科学中,链表是一种常见的数据结构,它将一系列元素组织成一个线性序列,每个元素都包含一个指向下一个元素的指针。当我们需要存储和处理具有复杂关系的数据时,链表是一种非常有用的数据结构。

在某些情况下,链表中的每个元素可能包含一个指向其他元素的随机指针,这种链表称为随机指针链表。随机指针链表在许多实际应用中都有用处,例如,在图形学中,随机指针链表可以用来表示三维模型中的顶点和边之间的关系;在自然语言处理中,随机指针链表可以用来表示单词之间的关系等等。

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

在LeetCode-138中,我们被要求复制一个具有随机指针的链表。具体来说,给定一个长度为n的链表,每个节点包含一个额外指向另一个节点的随机指针,我们要求复制出这个链表的一个完全相同的副本,包括随机指针。

解决方案

复制一个具有随机指针的链表有几种不同的方法,下面我们将介绍一些最常见的方法。

暴力法

暴力法是最简单的一种方法,它直接将链表中的每个节点复制一遍,然后将新节点的随机指针指向旧节点的随机指针。这种方法简单易懂,但时间复杂度为O(n^2),空间复杂度为O(n)。

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

    # 创建一个新链表
    new_head = ListNode(head.val)

    # 创建一个哈希表来存储旧节点和新节点之间的映射关系
    node_map = {head: new_head}

    # 复制链表中的每个节点
    current_node = head
    while current_node:
        new_node = node_map[current_node]
        if current_node.next:
            new_node.next = ListNode(current_node.next.val)
            node_map[current_node.next] = new_node.next
        if current_node.random:
            new_node.random = node_map[current_node.random]
        current_node = current_node.next

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

哈希表法

哈希表法与暴力法类似,但它使用哈希表来存储旧节点和新节点之间的映射关系,从而可以将时间复杂度降低到O(n)。

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

    # 创建一个哈希表来存储旧节点和新节点之间的映射关系
    node_map = {}

    # 复制链表中的每个节点
    current_node = head
    while current_node:
        new_node = ListNode(current_node.val)
        node_map[current_node] = new_node
        current_node = current_node.next

    # 更新新链表中每个节点的随机指针
    for old_node, new_node in node_map.items():
        new_node.random = node_map[old_node.random]

    # 返回新链表的头节点
    return node_map[head]

克隆法

克隆法是另一种复制具有随机指针的链表的方法,它将链表中的每个节点复制成两个节点,然后将新节点的随机指针指向旧节点的随机指针。最后,将新链表中的偶数节点删除,即可得到一个与旧链表完全相同的副本。

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

    # 将链表中的每个节点复制成两个节点
    current_node = head
    while current_node:
        new_node = ListNode(current_node.val)
        new_node.next = current_node.next
        current_node.next = new_node
        current_node = new_node.next

    # 更新新链表中每个节点的随机指针
    current_node = head
    while current_node:
        if current_node.random:
            current_node.next.random = current_node.random.next
        current_node = current_node.next.next

    # 将新链表中的偶数节点删除
    current_node = head
    while current_node:
        next_node = current_node.next
        current_node.next = next_node.next
        current_node = current_node.next

    # 返回新链表的头节点
    return head

总结

在本文中,我们介绍了LeetCode-138:“复制带随机指针的链表”问题的多种解决方案,包括暴力法、哈希表法和克隆法。每种方法都有其自身的优缺点,读者可以根据自己的需要选择最适合的方法。