链表-复杂链表的复制

72 阅读1分钟

剑指 Offer 35. 复杂链表的复制

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

示例 1:

image.png

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

示例 2:

image.png

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

示例 3:

image.png

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

示例 4:

输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null

题解1: 哈希表,时间O(N),空间O(N)

/**
 * // Definition for a Node.
 * function Node(val, next, random) {
 *    this.val = val;
 *    this.next = next;
 *    this.random = random;
 * };
 */

/**
 * @param {Node} head
 * @return {Node}
 */
var copyRandomList = function(head) {
    if(!head) return null

    let cur = head
    const hashmap = new Map()
    while(cur){
        hashmap.set(cur,new Node(cur.val,null,null))
        cur = cur.next
    }

    cur = head
    while(cur){
        hashmap.get(cur).next = hashmap.get(cur.next) || null
        hashmap.get(cur).random = hashmap.get(cur.random)
        cur = cur.next
    }

    return hashmap.get(head)
};

题解2: 拼接 + 拆分,时间O(N) 空间O(1)

/**
 * // Definition for a Node.
 * function Node(val, next, random) {
 *    this.val = val;
 *    this.next = next;
 *    this.random = random;
 * };
 */

/**
 * @param {Node} head
 * @return {Node}
 */
var copyRandomList = function(head) {
    if(!head) return null

    let cur = head
    //拼接新节点
    while(cur){
        const node = new Node(cur.val,null,null)
        node.next = cur.next
        cur.next = node

        cur = node.next
    }
    //修改新节点的random指向
    cur = head
    while(cur){
        if(cur.random){
            cur.next.random = cur.random.next
        }

        cur = cur.next.next
    }

    //拆分
    cur = head.next
    let pre = head
    let res = cur
    //存在cur.next节点就循环
    while(cur.next){
        //cur.next 为null时进不来
        //此时的pre还是上一个原节点
        pre.next = pre.next.next
        pre = pre.next
        
        cur.next = cur.next.next
        cur = cur.next

    }
    //此时,需将原尾节点置空
    pre.next = null

    return res
};

规则:

哈希表:构建原链表节点和新链表对应节点的键值对映射关系,再遍历构建新链表各节点的nextrandom指向。

题目来源:LeetCode