【Leetcode】138. 随机链表的复制

34 阅读1分钟

leetcode-138.png

A -> B -> C

我们可以采用一个 三步走策略 来完成深拷贝:

  1. 克隆节点并插入原链表
    在每个原节点后面插入一个新节点,得到:

    A -> A' -> B -> B' -> C -> C'
    
  2. 复制 random 指针
    对于原链表中的每个节点,如果 A.random = C,那么它的克隆节点 A' 应该指向 C'
    利用 cur.next 就能找到克隆节点,进而把 random 正确指过去。

  3. 拆分链表
    把原链表和新链表分开:

    • 原链表恢复为:A -> B -> C
    • 新链表得到:A' -> B' -> C'

这样,新链表就被成功构造出来了。

var copyRandomList = function (head) {
    if (!head) return null;
    let cur = head;
    // A -> A' -> B -> B' -> C -> C'
    while (cur) {
        let clone = new Node(cur.val);
        clone.next = cur.next;
        cur.next = clone;
        cur = clone.next;
    }
    // random point
    cur = head;
    while (cur) {
        if (cur.random) {
            cur.next.random = cur.random.next; // A' = C'
        }
        cur = cur.next.next; // A' -> B'
    }
    // split
    cur = head;
    let cloneHead = cur.next;
    while (cur) {
        let clone = cur.next;
        cur.next = clone.next;
        if (clone.next) {
            clone.next = clone.next.next;
        }
        cur = cur.next;
    }
    return cloneHead;
};

复杂度分析

  • 时间复杂度:O(n),三次遍历链表
  • 空间复杂度:O(1),不需要额外的数据结构(相比哈希表法更优雅)