题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
分析
思路(分三步):
1、复制每个结点,如将结点A’插到结点A后面,A’复制A
2、重新遍历链表,复制老结点的随机指针给新结点,如A指向C,那么A’也要指向C’
3、拆分链表,将链表拆分为原链表和复制后的链表,形成两条链表,返回复制后的链表
图解如下:
实现代码如下:
public class Solution {
public RandomListNode Clone(RandomListNode pHead)
{
if(pHead == null) {
return null;
}
RandomListNode curNode = pHead;
RandomListNode nextNode = null;
//1、复制每个结点,如将结点A'插到结点A后面,A'复制A
while (curNode != null) {
RandomListNode cloneNode = new RandomListNode(curNode.label);//创建复制结点
nextNode = curNode.next; //记录当前结点的下一个结点
cloneNode.next = nextNode;//这两步为连接操作
curNode.next = cloneNode;
curNode = nextNode;//往后走
}
curNode = pHead;
//2、重新遍历链表,复制老结点的随机指针给新结点,如A指向C,那么A'也要指向C'
while(curNode != null) {
// curNode.next表示复制结点,curNode.random.next表示要指向的另外一个复制结点,如上述A'指向C'
//因为新复制结点都在原结点的后面,所以用next即可表示新结点
curNode.next.random = (curNode.random == null ? null : curNode.random.next);
curNode = curNode.next.next;//走到下一个原结点位置
}
//3、拆分链表,将链表拆分为原链表和复制后的链表,形成两条链表,返回复制后的链表
curNode = pHead;
RandomListNode cloneHead = pHead.next;
RandomListNode cloneNode = null;
while (curNode != null) {
cloneNode = curNode.next;
curNode.next = cloneNode.next;
// 如果cloneNode.next为空的话
cloneNode.next = (cloneNode.next == null ? null : cloneNode.next.next);
curNode = curNode.next;
}
return cloneHead;
}
}