leetcode
leetcode 2601 ~ 2650
复杂链表的复制

复杂链表的复制

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 44 ms, 内存: 15.6 MB


/*
 * Java Stream不适合处理复杂链表的复制问题,因此这里提供一种简化的非标准实现。
 * 思路:
 * 1. 使用HashMap来存储原节点与新节点之间的映射关系。
 * 2. 先复制所有的节点,然后复制所有的next和random指针。
 */
import java.util.*;

class Node {
    int val;
    Node next;
    Node random;
    Node(int val) {
        this.val = val;
        this.next = null;
        this.random = null;
    }
}

public Node copyRandomList(Node head) {
    if (head == null) return null;
    Map<Node, Node> map = new HashMap<>();

    // 复制所有的节点
    Node current = head;
    while (current != null) {
        map.put(current, new Node(current.val));
        current = current.next;
    }

    // 复制next和random指针
    current = head;
    while (current != null) {
        map.get(current).next = map.get(current.next);
        map.get(current).random = map.get(current.random);
        current = current.next;
    }

    return map.get(head);
}

解释

方法:

这个题解采用了三步走的策略: 1. 遍历原始链表,对于每个节点,在其后面创建一个新的节点,其值与原节点相同。 2. 再次遍历链表,这次设置新节点的random指针,使其指向原节点random指针所指向的节点的下一个节点(即复制的节点)。 3. 最后,将链表拆分为原链表和复制的链表,返回复制的链表的头节点。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在第二步中,将新节点的random指针设置为原节点的random指针所指向的节点的下一个节点时,如何确保原节点的random指针所指向的节点已经被复制并具有next指针?
在第一步中,我们已经为链表的每个节点创建了一个复制节点,并将其插入到每个原节点和其next节点之间。因此,当我们在第二步中设置复制节点的random指针时,可以确信每个原节点的random指针所指向的节点已经在其后面有一个复制节点。这是因为第一步的操作确保了链表中每个节点后都紧跟着它的复制节点,包括原节点random指针所指向的节点。
🦆
在第三步拆分链表时,对于最后一个节点的处理有何特殊考虑,以确保原链表和复制链表都能正确结束?
在第三步拆分链表的过程中,最后一个节点的处理需要特别注意,以确保不会出现连接错误或丢失节点。对于原链表的最后一个节点,它的next应该指向null,同样,复制链表的最后一个节点也应该指向null。在拆分时,我们遍历链表,将每个原节点的next指向其next的next,即恢复原链表的连接,同时也将每个复制节点的next指向其next的next,以构建完整的复制链表。这确保了两个链表在结尾处正确地结束,没有多余或丢失的连接。
🦆
如何处理原始链表中存在循环引用的情况,例如一个节点的random指针指向自己或形成较长的环状结构?
在复制具有循环引用的链表时,算法仍然有效。由于每个节点的复制节点都紧接在原节点后面,即使是原节点的random指针指向自身或形成一个环,复制节点的random指针也会正确指向对应的复制节点,保持循环结构不变。例如,如果一个原节点的random指向自己,那么这个节点的复制节点的random也会指向它自己(即原节点的next)。这种方法自然地保留了原链表中的所有循环引用和复杂结构。
🦆
如果原链表为空(即head为None),题解中的函数似乎会返回None,这符合预期吗?如何验证这一行为是否正确?
是的,如果输入的原链表为空,即head为None,那么按照题解中的函数实现,返回的确实是None。这是符合预期的,因为没有节点可以复制。验证这一行为的正确性可以通过单元测试,例如传递一个空链表给函数,并检查返回值是否为None。这样可以确认函数在面对空输入时的行为是按预期工作的。

相关问题