题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
实现
代码最后一段不太好理解,参考lc的
复杂度O(n),不使用辅助空间
第一步:根据原始链表的每个节点N创建N’,直接放在N后。
第二步:设置复制的节点的特殊指针。存在N->S,则N’->S’。
第三步,按奇偶位将长链表茶分为两个链表
public class C35_list_CloneList {
public static class RandomListNode {
int val;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int val) {
this.val = val;
}
}
public static RandomListNode Clone(RandomListNode head) {
if (head == null) {
return null;
}
RandomListNode node = head;
//1、复制每个结点,如复制结点A得到A1,将结点A1插到结点A后面;
while (node != null) {
RandomListNode cloned = new RandomListNode(node.val);
RandomListNode next = node.next;
node.next = cloned;
cloned.next = next;
node = next;
}
node = head;
//2、重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next;
while (node != null) {
node.next.random = node.random == null ? null : node.random.next;//node.next为克隆节点
node = node.next.next;
}
//3、拆分链表,将链表拆分为原链表和复制后的链表
node = head;
RandomListNode cloneHead = head.next;
while (node != null) {
RandomListNode cloneNode = node.next;
node.next = cloneNode.next;
cloneNode.next = cloneNode.next == null ? null : cloneNode.next.next;
node = node.next;
}
return cloneHead;
}
}
Test
public static void main(String[] args) {
RandomListNode node1 = new RandomListNode(1);
RandomListNode node2 = new RandomListNode(2);
RandomListNode node3 = new RandomListNode(3);
RandomListNode node4 = new RandomListNode(4);
RandomListNode node5 = new RandomListNode(5);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node1.random = node3;
node2.random = node5;
node4.random = node2;
RandomListNode head = Clone(node1);
while (head != null) {
System.out.print(head.val);
if (head.random != null) {
System.out.print(" " + head.random.val);
}
head = head.next;
System.out.println();
}
}
输出
1 3
2 5
3
4 2
5