题目介绍
力扣138题:leetcode-cn.com/problems/co…
分析
题目要求我们复制一个长度为 n 的链表,该链表除了每个节点有一个指针指向下一个节点外,还有一个额外的指针指向链表中的任意节点或者 null,如下图所示:
如何去复制一个带随机指针的链表?
首先我们可以忽略 random 指针,然后对原链表的每个节点进行复制,并追加到原节点的后面,而后复制 random 指针。最后我们把原链表和复制链表拆分出来,并将原链表复原。
图示过程如下:
1、在每个节点的后面加上它的复制,并将原链表和复制链表连在一起。
2、 从前往后遍历每一个原链表节点,对于有 random 指针的节点 p,我们让它的 p->next->random = p->random->next,这样我们就完成了对原链表 random 指针的复刻。
3、最后我们把原链表和复制链表拆分出来,并将原链表复原。
具体过程如下:
- 1、定义一个 p 指针,遍历整个链表,复制每个节点,并将原链表和复制链表连在一起。
- 2、再次遍历整个链表,执行 p->next->random = p->random->next,复制 random 指针。
- 3、定义虚拟头节点 dummy 用来指向复制链表的头节点, 将两个链表拆分并复原原链表。
代码如下:
/*
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
*/
class Solution {
public Node copyRandomList(Node head) {
if(head == null) {
return null;
}
//复制每个节点,并将原链表和复制链表连在一起。
for(Node p = head; p != null; p = p.next.next) {
Node q = new Node(p.val);
q.next = p.next;
p.next = q;
}
//复制random指针
for(Node p = head; p != null; p = p.next.next) {
if(p.random != null) {
p.next.random = p.random.next;
}
}
//拆分两个链表,并复原原链表,哑结点
Node dummy = new Node(-1);
Node cur = dummy;
for(Node p = head; p != null; p = p.next) {
Node q = p.next;
cur.next = q;
cur = cur.next;
p.next = q.next;
}
return dummy.next;
}
}
时间复杂度分析: O(n),其中 n 是链表的长度。
空间复杂度分析: O(1)。