题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
解题思路:参考https://blog.csdn.net/zxm1306192988/article/details/81041589
不用辅助空间,实现 O(n) 的时间效率。
第一步仍然是根据原始链表的每个结点N 创建对应的 N‘ 。这一次把 N‘ 链接在N的后面。
第二步设置复制出来的结点的 random。
第三步把长链表拆分成两个链表:把奇数位置的结点用 next 链接起来就是原始链表,把偶数位置的结点用 next 链接起来就是复制出来的链表。
代码及注释如下:
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
public RandomListNode Clone(RandomListNode pHead) {
if (pHead == null) {
return pHead;
}
//1.将复制结点连到相应结点的后面
RandomListNode pNode = pHead;//复制一个头结点作为遍历用的指针
while (pNode != null) {
RandomListNode node = new RandomListNode(pNode.label);//注意新链表结构里面的值不是val而是label
node.next = pNode.next;
pNode.next = node;//插入中间节点是先后再前的,遇到相同的情况不要写错
pNode = node.next;//两步到达下一个待复制的值
}
//2.设置random指针
pNode = pHead;//重新指向链表头
while (pNode != null) {
if(pNode.random!=null){//有的节点没有random,所以要判断一下
pNode.next.random = pNode.random.next;
//复制链表的random指针指向,原链表的random指向的结点的下一个结点
}
pNode = pNode.next.next;//两步到达下一个待处理结点
}
//3.拆分两个链表,奇数位置为原链表,偶数位置为新链表,两个链表一毛一样
pNode = pHead;//pNode重新指向链表头
RandomListNode pHeadCopy = pNode.next;//保留复制链表头
RandomListNode pNodeCopy=pHeadCopy;//指向复制链表头
//pNode连接pNodeCopy后面的那个奇数结点,并前移
//初始状态pNodeCopy在前,pNode在后
//因此while(pNode!=null)而且先移动pNodeCopy后移动pNode
pNode.next=pNodeCopy.next;
pNode=pNode.next;
while(pNode!=null){
pNodeCopy.next=pNode.next;//pNodeCopy连接下一个偶数结点,并前移
pNodeCopy=pNodeCopy.next;
pNode.next=pNodeCopy.next;//pNode连接下一个奇数结点,并前移
pNode=pNode.next;
}
return pHeadCopy;
}
}