前言
这道题应该算是链表访问之后更加升级的一道题目,非常考察我们对链表的理解以及代码的把控,复杂程度不高,但是很好的训练了我们的代码熟练度。
题目描述
给你一个长度为 n
的链表,每个节点包含一个额外增加的随机指针 random
,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n
个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next
指针和 random
指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X
和 Y
两个节点,其中 X.random --> Y
。那么在复制链表中对应的两个节点 x
和 y
,同样有 x.random --> y
。
返回复制链表的头节点。
示例:
题目分析
这道题麻烦在,我们复制链表之后,还需要处理对应的random节点,如果直接复制链表,那很简单,如下即可
但是实际上我们还要处理random为对应的复制节点
我们题目处理分为以下三步:
1、一对一复制链表节点到新的链表 2、对应处理一对一节点的复制节点的random指针域 3、拆分链表为两个链表,并且对应返回复制节点的链表
即可完成题目。
所以代码应该怎么写呢?
代码实操演练
- 一对一复制链表节点
let p = head;
let q;
// 将每个节点单独复制一份
while (p) {
q = new Node(p.val);
q.random = p.random;
q.next = p.next;
p.next = q;
p = q.next;
}
复制代码
此处做了如下操作:
- 处理对应random的值
p = head.next;
while (p) {
if (p.random) p.random = p.random.next;
(p = p.next) && (p = p.next);
}
复制代码
此处处理如下:
3.最终拆分为两个链表,并返回新的链表
let new_head = head.next;
p = head;
while (p) {
q = p.next;
p.next = q.next;
if (p.next) q.next = p.next.next;
p = p.next;
}
return new_head;
复制代码
完整效果: