1、题目描述
请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:
输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例 3:
输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例 4:
输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。
分析
简单来说就是进行三次遍历,第一次遍历将原链表的长度*2,即原链表为A→B→C,新链表为A→a→B→b→C→c。将原节点ABC拷贝至新节点abc,这样,我们可以通过第二次遍历直接找到每一个新节点的随机指针,将其原本指向的原节点ABC更改为指向abc,此时记得要判断null。
第三次遍历则是将原节点与新节点进行拆分。这样新节点便组成了我们想要的全新的链表。
var copyRandomList = function(head) {
if (head === null) {
return null;
}
// 因为注入了新节点,所以原节点的next此时变成了next.next
for (let node = head; node !== null; node = node.next.next) {
// 创建新节点,也是深拷贝的过程。
const nodeNew = new Node(node.val, node.next, null);
// 原节点的下一个节点指向新节点,新节点的下一个结点是原节点的原下一个节点
node.next = nodeNew;
}
// 第二次遍历,更改random的指向,每次循环都是遍历原节点所以是next.next
for (let node = head; node !== null; node = node.next.next) {
// 找到新节点
const nodeNew = node.next;
// 新节点的random指向新节点,注意判断null
nodeNew.random = (node.random !== null) ? node.random.next : null;
}
// 拆分新老节点。
const headNew = head.next;
for (let node = head; node !== null; node = node.next) {
const nodeNew = node.next;
node.next = node.next.next;
nodeNew.next = (nodeNew.next !== null) ? nodeNew.next.next : null;
}
return headNew;
};
欢迎建议讨论