public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
/*
思路:
在不用辅助空间的情况下实现 O(n)的时间效率。
一个含有 5 个结点的复杂链表。图中实线箭头表示 next 指针,虚线箭头表示 sibling 指针。为简单起见,指向 null 的指针没有画出。
1.:仍然是根据原始链表的每个结点ABCDE创建对应的 A’B'CDE'。把 N’链接在N的后面。图 4.8 的链表经过这一步之后的结构。
2.:设置复制出来的结点的 sibling。假设原始链表上的 N 的 sibling 指向结点 S,那么其对应复制出来的 N’是 N的 pext 指向的结点,同样 S’也是 S 的 next 指向的结点。
3.把这个长链表拆分成两个链表。把奇数位置的结点用 next 链接起来就是原始链表,把偶数位置的结点用 next 链接起来就是复制 出来的链表
public class Solution {
public RandomListNode copyRandomList(RandomListNode head) {
if (head == null) {
return null;
}
copyNode(head);
linkRandomPointer(head);
return splitList(head);
}
//第一步:复制结点,复制的结点放在待复制的结点后,依然组成一个单链表
public void copyNode(RandomListNode head) {
// 记录当前要被复制的缜
RandomListNode node = head;
while (node != null) {
// 复制一个新的结点
RandomListNode copyNode = new RandomListNode(node.label);
// 将结点串接到被复制的结点后,并且依然组成单链表
copyNode.next = node.next;//A->B A'->B
node.next = copyNode;//A->A'
node = copyNode.next;//不断循环 B
}
}
// 第二步:串接随机指针
public void linkRandomPointer(RandomListNode head) {
// 记录当前要被复制的缜
RandomListNode node = head;
while (node != null) {
// 随机指针有指向某个具体的结点
if (node.random != null) {
// 串接node被复制结点的随机指针
node.next.random = node.random.next;//
}
// 指向下一个被复制的结点
node = node.next.next;
}
}
/**
*第三步: 将链表拆分,还原原来的链表,并且组装拷贝的链表
* @param head 链表头
* @return 拷贝的新链表头
*/
public RandomListNode splitList(RandomListNode head) {
// 新链表头
RandomListNode copyHead = head.next;
// 当前处理的被复制的结点
RandomListNode node = head;
// 当前复制的结点
RandomListNode copy;
while (node != null){
// 指向复制结点
copy = node.next;
// node.next指向下一个被复制的结点
node.next = copy.next;
// 下一个被复制的结点不为null
if (node.next != null) {
// copy.next指向下一个复制的结点
copy.next = node.next.next;
}
// node指向下一个要被处理的被复制结点
node = node.next;
}
return copyHead;
}
}