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

初步解决

思路:由于题目中的链表节点有一个随机指针,所以从头节点按顺序复制的话,可能出现指向的随机节点还没有被复制的问题,故考虑先按顺序复制,并将指针都设为null,用哈希表保存每个节点对应的副本,再将节点的指针连起来

代码(js):

const copyRandomList = function(head) {
    if(!head) { return null }
    let curr = head
    const nodeMap = new Map()
    while(curr) {
        nodeMap.set(curr, {val:curr.val, next:null, random:null})
        curr = curr.next
    }
    curr = head
    while(curr) {
        nodeMap.get(curr).next = nodeMap.get(curr.next) || null
        nodeMap.get(curr).random = nodeMap.get(curr.random) || null
        curr = curr.next
    }
    return nodeMap.get(head)
};

复杂度分析:这样做需要遍历两次初始链表,且需要哈希表保存原节点和对应副本节点,时间复杂度O(n),空间复杂度O(n)

优化

思路:上面的思路中指向的随机节点还没有被复制可以用递归来解决,在一次遍历中直接复制节点,若节点的next或者random指针还没有被创建,则递归复制节点

代码(js):

const copyRandomList = function(head, map = new Map()) {
    if(!head) { return null }
    if (!map.has(head)) {
        map.set(head, { val: head.val })
        Object.assign(map.get(head), {next: copyRandomList(head.next, map), random: copyRandomList(head.random, map)})
    }
    return map.get(head)
};

复杂度分析:与上面的代码相同,都需要遍历链表及创建哈希表,故复杂度都为O(n)

其他方法:迭代-节点拆分(个人认为方法虽然巧妙但不够简洁…)

Leave a Reply

Your email address will not be published. Required fields are marked *