复杂链表的复制
题目
代码
class Solution {
public Node copyRandomList(Node head) {
// 处理特殊情况,如果头节点为空,则返回null
if (head == null) {
return null;
}
// 第一步:构建一个组合链表
Node cur = head;
while (cur != null) {
Node tmp = new Node(cur.val); // 创建一个新节点,值为当前节点的值
tmp.next = cur.next; // 将新节点的next指针指向当前节点的下一个节点
cur.next = tmp; // 将当前节点的next指针指向新节点,实现插入操作
cur = tmp.next; // 更新当前节点为原节点的下一个节点
}
// 第二步:构建random指针
cur = head;
while (cur != null) {
if (cur.random != null) {
cur.next.random = cur.random.next; // 复制节点的random指针指向原节点的random指针的下一个节点
}
cur = cur.next.next; // 更新当前节点为原节点的下一个节点的下一个节点
}
// 第三步:拆分链表
Node res = head.next; // 复制链表的头节点
cur = head.next; // 当前节点指向复制链表的头节点
Node pre = head; // 前一个节点指向原链表的头节点
while (cur.next != null) {
pre.next = pre.next.next; // 恢复原链表的next指针
cur.next = cur.next.next; // 恢复复制链表的next指针
pre = pre.next; // 更新前一个节点为原链表的下一个节点
cur = cur.next; // 更新当前节点为复制链表的下一个节点
}
pre.next = null; // 单独处理最后一个节点,将其next指针设置为null
// 返回复制链表的头节点
return res;
}
}
题解
在复制链表的过程中,我们需要处理每个节点的random指针。random指针指向链表中的任意节点或者null。为了正确复制random指针,我们需要遵循以下步骤:
- 第一步:复制节点并插入到原节点的后面。
- 对于每个原节点,我们创建一个新节点,并将其插入到原节点的后面。这样原链表的结构就变成了:原节点 -> 新节点 -> 原节点的下一个节点。
- 第二步:设置复制节点的
random
指针。- 对于每个原节点,我们将新节点的
random
指针指向原节点的random
指针的下一个节点。这是因为在第一步中,我们已经将新节点插入到了原节点的后面,所以新节点的位置就是原节点的下一个节点。
- 对于每个原节点,我们将新节点的
- 第三步:拆分链表,恢复原链表和复制链表。
- 在第一步和第二步完成之后,我们得到了一个组合链表,其中原节点和复制节点交替出现。现在我们需要将组合链表拆分为原链表和复制链表。
- 遍历组合链表,通过调整每个节点的
next
指针,将原链表和复制链表分离开来。 - 最后返回复制链表的头节点作为结果。