Const
假如没有random指针,深拷贝一条普通链表,只需要按顺序复制链表的val和next指针,因为每个节点和下一个节点是按顺序一一对应的。现在增加了random指针带来的麻烦就是,当前复制节点的random可能还没有被遍历到并复制下来。所以无法在顺序遍历的时候直接确定下来random节点。由于我们知道不管怎样,链表上各节点的random总是指向链表上的其他节点的。如果我们能够记住新节点到旧节点的关系,先通过当前节点找回自己的旧节点,再从旧节点找到对应的原链表上的random节点。因为原链表上的这个random节点本身也是链表上的节点,那么我们可以再次映射回到新链表上的对应节点,而这个对应的新节点就是新的random节点。 比如1->2->3-null(old),假设1的random是3。那么我们可以先复制除了random之外的所有属性,1->2->3-null(new)。接着我们建立两个map,分别是newToOld和oldToNew:
function copyRandomList(head: _Node | null): _Node | null {
const dummy = new _Node(-1);
let tail = dummy;
let l1 = head;
let l2 = dummy;
const newToOld = new WeakMap<_Node, _Node>();
const oldToNew = new WeakMap<_Node, _Node>();
// 复制原链表
while (l1) {
l2 = new _Node(l1.val);
tail.next = l2;
newToOld.set(l2, l1);
oldToNew.set(l1, l2);
tail = tail.next;
l1 = l1.next;
}
// 完成random指向
l2 = dummy.next!;
while (l2) {
const old = newToOld.get(l2)!;
const newRandom = oldToNew.get(old.random!)!;
l2.random = newRandom;
l2 = l2.next!;
}
return dummy.next;
};
138.随机链表的复制
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 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]]
提示:
0 <= n <= 1000
-10^4 <= Node.val <= 10^4
Node.random
为空(null)或指向链表中的节点。