题意大致是这样的:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的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; //返回复制节点的头节点 } }