32.随机链表的复制

5 阅读1分钟

题目链接

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

解法 暴力解法map+两次遍历

思路

深复制需要复制原链表的 random 关系,而在遍历过程中,可能 random 上的新节点还没有被创建出来,无法实现,所以需要两次遍历。

可以第一次遍历先创建节点,并且使用 map 来保存新链表和老链表之间各个节点的对应关系,在第二次遍历中再去关联新链表的 random 指针。

代码

function copyRandomList(head: _Node | null): _Node | null {
    const map = new Map<_Node, _Node>();
    let dummyHead = new _Node(-1);
    let cur = dummyHead;
    let current = head;
    while (current) {
        const node = new _Node(current.val);
        map.set(current, node);

        cur.next = node;
        cur = cur.next;
        current = current.next;
    }

    current = head;
    cur = dummyHead.next;
    while (current) {
        cur.random = map.get(current.random) ?? null;
        cur = cur.next;
        current = current.next;
    }

    return dummyHead.next;
};

时空复杂度

时间复杂度:没有嵌套遍历 O(n)

空间复杂度:缓存了所有链表节点所以是 O(n)