剑指 Offer 35. 复杂链表的复制
请实现 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。
提示:
-10000 <= Node.val <= 10000
Node.random
为空(null
)或指向链表中的节点。- 节点数目不超过
1000
。
注意:
本题与主站 138 题相同:https://leetcode-cn.com/problems/copy-list-with-random-pointer/
[HTML_REMOVED]
解题思路
我们假设原链表如下图所示,为了图简洁清晰,我们简化了示例1
中的图,只让13
和11
的random
不为空,此外不管是next
指针还是random
指针,指向空的均未画出,红色表示random
指针。
第一步: 我们可以将每个节点都先复制一遍(此时复制时,random
指针暂时不管),并接在原节点和其下一个节点的中间,如下图:
第二步: 复制random
节点,遍历原链表的每一个节点,让p.next.random = p.random.next;
如图中蓝色的13
节点,当执行p.next.random = p.random.next
后,就是绿色的13
节点的random
指针指向了绿色的7
节点,也即完成了一个节点的random
指针的复制,后面的节点以此类推。
第三步: 分开两个链表,并将原链表还原。
[HTML_REMOVED]
Java代码
/*
// 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;
//第一步:复制每个节点,并插在原节点和其下一个节点之间
Node cur = head;
while(cur != null){
Node copy = new Node(cur.val);
copy.next = cur.next;
cur.next = copy;
cur = cur.next.next;;
}
//第二步:复制random指针
cur = head;
while(cur != null ){
if(cur.random != null){
cur.next.random = cur.random.next;
}
cur = cur.next.next;
}
//第三步:分开两个链表,并将原链表还原。
Node dummy = new Node(-1);//复制链表的虚拟头节点
Node help = dummy;//辅助建立复制的链表
cur = head;
while(cur != null){
help.next = cur.next;
help = help.next;
cur.next = cur.next.next;
cur = cur.next;
}
return dummy.next;
}
}