题意大致是这样的:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
分析 如果我们复制一个节点后就立即指定它的random节点可能会出现这种情况,即它的random节点还没有复制过来,这将会导致出错,故我们可以分两步进行 首先在复制链表时 先不管其random指针,在复制完成后 在从表头节点开始重新为每个节点添加random指针,具体的可以看操作过程可以看下图:
下面是具体的实现代码 :
package com.ACM;
import java.util.HashMap;
public class Solution {
static class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
public RandomListNode Clone(RandomListNode pHead) {
RandomListNode pHead1 = pHead; //因为头结点会被反复用到,所以我们新建一个指针指向头结点
RandomListNode cloneHead = null; //复制链表的头结点
if (pHead == null) { //为空直接返回
return null;
}
cloneHead = new RandomListNode(pHead.label); //不为空创建头结点
RandomListNode cloneHead1 = cloneHead;
//先处理每个节点的next节点,进行复制 ,不要管random节点 ,
while (pHead1.next != null) {
RandomListNode tmp = pHead1.next;
RandomListNode newListNode = new RandomListNode(tmp.label);
cloneHead1.next = newListNode;
pHead1 = tmp;
cloneHead1 = newListNode;
}
//接着对链表节点中的每一个random进行处理
//先重新获取原链表和复制链表的表头节点
RandomListNode cloneHead2 = cloneHead;
RandomListNode pHead2 = pHead;
RandomListNode pheadMove = pHead;
RandomListNode cloneHeadMove = cloneHead;
while (pHead2 != null && cloneHead2 != null) {
RandomListNode tmp = pHead2.random;
//从两个链表的头结点一起移动,当原链表移动到random
//复制链表的头结点也移动到了该节点的random
while (pheadMove != null && cloneHeadMove != null) {
if (pheadMove == tmp) { //找到他的randdom节点 结束循环
break;
}
pheadMove = pheadMove.next; //没找到 两个链表的指针都往后移
cloneHeadMove = cloneHeadMove.next;
}
cloneHead2.random = cloneHeadMove;
pheadMove = pHead; //每次都是从头结点开始寻找的
cloneHeadMove = cloneHead;
pHead2 = pHead2.next; //替下一个节点找它的random节点
cloneHead2 = cloneHead2.next;
}
return cloneHead; //返回复制节点的头节点
}
}